Pothos  0.7.0-gf7fbae99
The Pothos dataflow programming software suite
SpinLockRW.hpp
Go to the documentation of this file.
1 
11 #pragma once
12 #include <Pothos/Config.hpp>
13 #include <thread>
14 #include <atomic>
15 
16 namespace Pothos {
17 namespace Util {
18 
23 template <typename T>
25 {
26 public:
27  SharedLock(T &mutex):
28  _mutex(mutex)
29  {
30  _mutex.lock_shared();
31  }
32 
34  {
35  _mutex.unlock_shared();
36  }
37 
38 private:
39  T &_mutex;
40 };
41 
53 {
54 public:
55 
58 
60  SpinLockRW(void);
61 
63  bool try_lock_shared(void) noexcept;
64 
66  void lock_shared(void) noexcept;
67 
69  void unlock_shared(void) noexcept;
70 
72  bool try_lock(void) noexcept;
73 
75  void lock(void) noexcept;
76 
78  void unlock(void) noexcept;
79 
80 private:
81  enum : unsigned {WRITER_LOCK = unsigned(~0), UNLOCKED = 0};
82  std::atomic<unsigned> _lock;
83 };
84 
85 } //namespace Util
86 } //namespace Pothos
87 
88 
90 {
91  this->unlock();
92 }
93 
95 {
96  //true when the expected condition is not write lock
97  //and swap in the value of expected +1 (additional reader)
98  unsigned expected = _lock.load(std::memory_order_acquire);
99  return expected != WRITER_LOCK and _lock.compare_exchange_weak(expected, expected+1, std::memory_order_acq_rel);
100 }
101 
102 inline void Pothos::Util::SpinLockRW::lock_shared(void) noexcept
103 {
104  size_t count(0);
105  while (not this->try_lock_shared())
106  {
107  if (++count > 1024) std::this_thread::yield();
108  }
109 }
110 
111 inline void Pothos::Util::SpinLockRW::unlock_shared(void) noexcept
112 {
113  //decrement the reader count by 1
114  _lock.fetch_sub(1, std::memory_order_release);
115 }
116 
117 inline bool Pothos::Util::SpinLockRW::try_lock(void) noexcept
118 {
119  //true when the expected condition is unlocked (no readers)
120  //and swap in the value of write lock (one writer)
121  unsigned expected = UNLOCKED;
122  return _lock.compare_exchange_weak(expected, WRITER_LOCK, std::memory_order_acq_rel);
123 }
124 
125 inline void Pothos::Util::SpinLockRW::lock(void) noexcept
126 {
127  size_t count(0);
128  while (not this->try_lock())
129  {
130  if (++count > 1024) std::this_thread::yield();
131  }
132 }
133 
134 inline void Pothos::Util::SpinLockRW::unlock(void) noexcept
135 {
136  //restore to unlocked (no writer, no readers)
137  _lock.store(UNLOCKED, std::memory_order_release);
138 }
void unlock(void) noexcept
Unlock single writer access.
Definition: SpinLockRW.hpp:134
#define POTHOS_API
Definition: Config.hpp:41
Pothos::Util::SharedLock< SpinLockRW > SharedLock
Convenient typedef for shared lock type.
Definition: SpinLockRW.hpp:57
Definition: ArchiveEntry.hpp:20
~SharedLock(void)
Definition: SpinLockRW.hpp:33
bool try_lock_shared(void) noexcept
Try to lock shared, return true for lock.
Definition: SpinLockRW.hpp:94
Definition: SpinLockRW.hpp:52
void lock(void) noexcept
Lock for single writer access.
Definition: SpinLockRW.hpp:125
void unlock_shared(void) noexcept
Unlock from multiple reader access.
Definition: SpinLockRW.hpp:111
void lock_shared(void) noexcept
Lock for multiple reader access.
Definition: SpinLockRW.hpp:102
SpinLockRW(void)
Create a new unlocked spin lock.
Definition: SpinLockRW.hpp:89
SharedLock(T &mutex)
Definition: SpinLockRW.hpp:27
Definition: SpinLockRW.hpp:24
bool try_lock(void) noexcept
Try to lock, return true for lock.
Definition: SpinLockRW.hpp:117