1 // 2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 #pragma once 8 9 #include "td/utils/port/thread.h" 10 11 #include <atomic> 12 #include <memory> 13 14 namespace td { 15 16 class SpinLock { 17 struct Unlock { operatorUnlock18 void operator()(SpinLock *ptr) { 19 ptr->unlock(); 20 } 21 }; 22 23 class InfBackoff { 24 int cnt = 0; 25 26 public: next()27 bool next() { 28 cnt++; 29 if (cnt < 50) { 30 //TODO pause 31 return true; 32 } else { 33 td::this_thread::yield(); 34 return true; 35 } 36 } 37 }; 38 39 public: 40 using Lock = std::unique_ptr<SpinLock, Unlock>; 41 lock()42 Lock lock() { 43 InfBackoff backoff; 44 while (!try_lock()) { 45 backoff.next(); 46 } 47 return Lock(this); 48 } try_lock()49 bool try_lock() { 50 return !flag_.test_and_set(std::memory_order_acquire); 51 } 52 53 private: 54 std::atomic_flag flag_ = ATOMIC_FLAG_INIT; unlock()55 void unlock() { 56 flag_.clear(std::memory_order_release); 57 } 58 }; 59 60 } // namespace td 61