Fabcoin Core  0.16.2
P2P Digital Currency
sync.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2017 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef FABCOIN_SYNC_H
7 #define FABCOIN_SYNC_H
8 
9 #include <threadsafety.h>
10 
11 #include <boost/thread/condition_variable.hpp>
12 #include <boost/thread/mutex.hpp>
13 #include <boost/thread/recursive_mutex.hpp>
14 
15 
17 // //
18 // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
19 // //
21 
22 /*
23 CCriticalSection mutex;
24  boost::recursive_mutex mutex;
25 
26 LOCK(mutex);
27  boost::unique_lock<boost::recursive_mutex> criticalblock(mutex);
28 
29 LOCK2(mutex1, mutex2);
30  boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1);
31  boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2);
32 
33 TRY_LOCK(mutex, name);
34  boost::unique_lock<boost::recursive_mutex> name(mutex, boost::try_to_lock_t);
35 
36 ENTER_CRITICAL_SECTION(mutex); // no RAII
37  mutex.lock();
38 
39 LEAVE_CRITICAL_SECTION(mutex); // no RAII
40  mutex.unlock();
41  */
42 
44 // //
45 // THE ACTUAL IMPLEMENTATION //
46 // //
48 
53 template <typename PARENT>
54 class LOCKABLE AnnotatedMixin : public PARENT
55 {
56 public:
58  {
59  PARENT::lock();
60  }
61 
63  {
64  PARENT::unlock();
65  }
66 
68  {
69  return PARENT::try_lock();
70  }
71 };
72 
73 #ifdef DEBUG_LOCKORDER
74 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
75 void LeaveCritical();
76 std::string LocksHeld();
77 void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
78 void DeleteLock(void* cs);
79 #else
80 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
81 void static inline LeaveCritical() {}
82 void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
83 void static inline DeleteLock(void* cs) {}
84 #endif
85 #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
86 
91 class CCriticalSection : public AnnotatedMixin<boost::recursive_mutex>
92 {
93 public:
95  DeleteLock((void*)this);
96  }
97 };
98 
101 
103 typedef boost::condition_variable CConditionVariable;
104 
105 #ifdef DEBUG_LOCKCONTENTION
106 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
107 #endif
108 
110 template <typename Mutex>
112 {
113 private:
114  boost::unique_lock<Mutex> lock;
115 
116  void Enter(const char* pszName, const char* pszFile, int nLine)
117  {
118  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
119 #ifdef DEBUG_LOCKCONTENTION
120  if (!lock.try_lock()) {
121  PrintLockContention(pszName, pszFile, nLine);
122 #endif
123  lock.lock();
124 #ifdef DEBUG_LOCKCONTENTION
125  }
126 #endif
127  }
128 
129  bool TryEnter(const char* pszName, const char* pszFile, int nLine)
130  {
131  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
132  lock.try_lock();
133  if (!lock.owns_lock())
134  LeaveCritical();
135  return lock.owns_lock();
136  }
137 
138 public:
139  CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, boost::defer_lock)
140  {
141  if (fTry)
142  TryEnter(pszName, pszFile, nLine);
143  else
144  Enter(pszName, pszFile, nLine);
145  }
146 
147  CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
148  {
149  if (!pmutexIn) return;
150 
151  lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock);
152  if (fTry)
153  TryEnter(pszName, pszFile, nLine);
154  else
155  Enter(pszName, pszFile, nLine);
156  }
157 
159  {
160  if (lock.owns_lock())
161  LeaveCritical();
162  }
163 
164  operator bool()
165  {
166  return lock.owns_lock();
167  }
168 };
169 
171 
172 #define PASTE(x, y) x ## y
173 #define PASTE2(x, y) PASTE(x, y)
174 
175 #define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
176 #define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__)
177 #define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
178 
179 #define ENTER_CRITICAL_SECTION(cs) \
180  { \
181  EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
182  (cs).lock(); \
183  }
184 
185 #define LEAVE_CRITICAL_SECTION(cs) \
186  { \
187  (cs).unlock(); \
188  LeaveCritical(); \
189  }
190 
192 {
193 private:
194  boost::condition_variable condition;
195  boost::mutex mutex;
196  int value;
197 
198 public:
199  CSemaphore(int init) : value(init) {}
200 
201  void wait()
202  {
203  boost::unique_lock<boost::mutex> lock(mutex);
204  while (value < 1) {
205  condition.wait(lock);
206  }
207  value--;
208  }
209 
210  bool try_wait()
211  {
212  boost::unique_lock<boost::mutex> lock(mutex);
213  if (value < 1)
214  return false;
215  value--;
216  return true;
217  }
218 
219  void post()
220  {
221  {
222  boost::unique_lock<boost::mutex> lock(mutex);
223  value++;
224  }
225  condition.notify_one();
226  }
227 };
228 
231 {
232 private:
235 
236 public:
237  void Acquire()
238  {
239  if (fHaveGrant)
240  return;
241  sem->wait();
242  fHaveGrant = true;
243  }
244 
245  void Release()
246  {
247  if (!fHaveGrant)
248  return;
249  sem->post();
250  fHaveGrant = false;
251  }
252 
253  bool TryAcquire()
254  {
255  if (!fHaveGrant && sem->try_wait())
256  fHaveGrant = true;
257  return fHaveGrant;
258  }
259 
260  void MoveTo(CSemaphoreGrant& grant)
261  {
262  grant.Release();
263  grant.sem = sem;
264  grant.fHaveGrant = fHaveGrant;
265  fHaveGrant = false;
266  }
267 
268  CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
269 
270  CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false)
271  {
272  if (fTry)
273  TryAcquire();
274  else
275  Acquire();
276  }
277 
279  {
280  Release();
281  }
282 
283  operator bool()
284  {
285  return fHaveGrant;
286  }
287 };
288 
289 #endif // FABCOIN_SYNC_H
void MoveTo(CSemaphoreGrant &grant)
Definition: sync.h:260
void unlock() UNLOCK_FUNCTION()
Definition: sync.h:62
#define EXCLUSIVE_LOCK_FUNCTION(...)
Definition: threadsafety.h:43
boost::condition_variable CConditionVariable
Just a typedef for boost::condition_variable, can be wrapped later if desired.
Definition: sync.h:103
CMutexLock(Mutex &mutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(mutexIn)
Definition: sync.h:139
CMutexLock(Mutex *pmutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
Definition: sync.h:147
Definition: Log.h:35
~CMutexLock() UNLOCK_FUNCTION()
Definition: sync.h:158
RAII-style semaphore lock.
Definition: sync.h:230
CMutexLock< CCriticalSection > CCriticalBlock
Definition: sync.h:170
bool try_wait()
Definition: sync.h:210
void lock() EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:57
void Acquire()
Definition: sync.h:237
#define nullptr
Definition: eqcuda.hpp:22
#define UNLOCK_FUNCTION(...)
Definition: threadsafety.h:47
CSemaphoreGrant(CSemaphore &sema, bool fTry=false)
Definition: sync.h:270
~CSemaphoreGrant()
Definition: sync.h:278
void Enter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:116
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
Definition: sync.h:67
AnnotatedMixin< boost::mutex > CWaitableCriticalSection
Wrapped boost mutex: supports waiting but not recursive locking.
Definition: sync.h:100
CSemaphore * sem
Definition: sync.h:233
int value
Definition: sync.h:196
void Release()
Definition: sync.h:245
Wrapper around boost::unique_lock<Mutex>
Definition: sync.h:111
CSemaphoreGrant()
Definition: sync.h:268
boost::mutex mutex
Definition: sync.h:195
#define LOCKABLE
Definition: threadsafety.h:35
Template mixin that adds -Wthread-safety locking annotations to a subset of the mutex API...
Definition: sync.h:54
boost::condition_variable condition
Definition: sync.h:194
void wait()
Definition: sync.h:201
bool TryEnter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:129
#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
Definition: threadsafety.h:45
#define SCOPED_LOCKABLE
Definition: threadsafety.h:36
CSemaphore(int init)
Definition: sync.h:199
std::mutex Mutex
Definition: Guards.h:37
void post()
Definition: sync.h:219
bool TryAcquire()
Definition: sync.h:253
~CCriticalSection()
Definition: sync.h:94
bool fHaveGrant
Definition: sync.h:234
boost::unique_lock< Mutex > lock
Definition: sync.h:114
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
Definition: sync.h:91