Dash Core  0.12.2.1
P2P Digital Currency
sync.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2015 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 BITCOIN_SYNC_H
7 #define BITCOIN_SYNC_H
8 
9 #include "threadsafety.h"
10 
11 #include <boost/thread/condition_variable.hpp>
12 #include <boost/thread/locks.hpp>
13 #include <boost/thread/mutex.hpp>
14 #include <boost/thread/recursive_mutex.hpp>
15 
16 
18 // //
19 // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
20 // //
22 
23 /*
24 CCriticalSection mutex;
25  boost::recursive_mutex mutex;
26 
27 LOCK(mutex);
28  boost::unique_lock<boost::recursive_mutex> criticalblock(mutex);
29 
30 LOCK2(mutex1, mutex2);
31  boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1);
32  boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2);
33 
34 TRY_LOCK(mutex, name);
35  boost::unique_lock<boost::recursive_mutex> name(mutex, boost::try_to_lock_t);
36 
37 ENTER_CRITICAL_SECTION(mutex); // no RAII
38  mutex.lock();
39 
40 LEAVE_CRITICAL_SECTION(mutex); // no RAII
41  mutex.unlock();
42  */
43 
45 // //
46 // THE ACTUAL IMPLEMENTATION //
47 // //
49 
54 template <typename PARENT>
55 class LOCKABLE AnnotatedMixin : public PARENT
56 {
57 public:
59  {
60  PARENT::lock();
61  }
62 
64  {
65  PARENT::unlock();
66  }
67 
69  {
70  return PARENT::try_lock();
71  }
72 };
73 
79 
82 
84 typedef boost::condition_variable CConditionVariable;
85 
86 #ifdef DEBUG_LOCKORDER
87 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
88 void LeaveCritical();
89 std::string LocksHeld();
90 void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs);
91 #else
92 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
93 void static inline LeaveCritical() {}
94 void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs) {}
95 #endif
96 #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
97 
98 #ifdef DEBUG_LOCKCONTENTION
99 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
100 #endif
101 
103 template <typename Mutex>
105 {
106 private:
107  boost::unique_lock<Mutex> lock;
108 
109  void Enter(const char* pszName, const char* pszFile, int nLine)
110  {
111  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
112 #ifdef DEBUG_LOCKCONTENTION
113  if (!lock.try_lock()) {
114  PrintLockContention(pszName, pszFile, nLine);
115 #endif
116  lock.lock();
117 #ifdef DEBUG_LOCKCONTENTION
118  }
119 #endif
120  }
121 
122  bool TryEnter(const char* pszName, const char* pszFile, int nLine)
123  {
124  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
125  lock.try_lock();
126  if (!lock.owns_lock())
127  LeaveCritical();
128  return lock.owns_lock();
129  }
130 
131 public:
132  CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : lock(mutexIn, boost::defer_lock)
133  {
134  if (fTry)
135  TryEnter(pszName, pszFile, nLine);
136  else
137  Enter(pszName, pszFile, nLine);
138  }
139 
140  CMutexLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
141  {
142  if (!pmutexIn) return;
143 
144  lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock);
145  if (fTry)
146  TryEnter(pszName, pszFile, nLine);
147  else
148  Enter(pszName, pszFile, nLine);
149  }
150 
152  {
153  if (lock.owns_lock())
154  LeaveCritical();
155  }
156 
157  operator bool()
158  {
159  return lock.owns_lock();
160  }
161 };
162 
164 
165 #define PASTE(x, y) x ## y
166 #define PASTE2(x, y) PASTE(x, y)
167 
168 #define LOCK(cs) CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
169 #define LOCK2(cs1, cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), criticalblock2(cs2, #cs2, __FILE__, __LINE__)
170 #define TRY_LOCK(cs, name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
171 
172 #define ENTER_CRITICAL_SECTION(cs) \
173  { \
174  EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
175  (cs).lock(); \
176  }
177 
178 #define LEAVE_CRITICAL_SECTION(cs) \
179  { \
180  (cs).unlock(); \
181  LeaveCritical(); \
182  }
183 
185 {
186 private:
187  boost::condition_variable condition;
188  boost::mutex mutex;
189  int value;
190 
191 public:
192  CSemaphore(int init) : value(init) {}
193 
194  void wait()
195  {
196  boost::unique_lock<boost::mutex> lock(mutex);
197  while (value < 1) {
198  condition.wait(lock);
199  }
200  value--;
201  }
202 
203  bool try_wait()
204  {
205  boost::unique_lock<boost::mutex> lock(mutex);
206  if (value < 1)
207  return false;
208  value--;
209  return true;
210  }
211 
212  void post()
213  {
214  {
215  boost::unique_lock<boost::mutex> lock(mutex);
216  value++;
217  }
218  condition.notify_one();
219  }
220 };
221 
224 {
225 private:
228 
229 public:
230  void Acquire()
231  {
232  if (fHaveGrant)
233  return;
234  sem->wait();
235  fHaveGrant = true;
236  }
237 
238  void Release()
239  {
240  if (!fHaveGrant)
241  return;
242  sem->post();
243  fHaveGrant = false;
244  }
245 
246  bool TryAcquire()
247  {
248  if (!fHaveGrant && sem->try_wait())
249  fHaveGrant = true;
250  return fHaveGrant;
251  }
252 
253  void MoveTo(CSemaphoreGrant& grant)
254  {
255  grant.Release();
256  grant.sem = sem;
257  grant.fHaveGrant = fHaveGrant;
258  sem = NULL;
259  fHaveGrant = false;
260  }
261 
262  CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {}
263 
264  CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false)
265  {
266  if (fTry)
267  TryAcquire();
268  else
269  Acquire();
270  }
271 
273  {
274  Release();
275  }
276 
277  operator bool()
278  {
279  return fHaveGrant;
280  }
281 };
282 
283 #endif // BITCOIN_SYNC_H
#define EXCLUSIVE_LOCK_FUNCTION(...)
Definition: threadsafety.h:43
void Acquire()
Definition: sync.h:230
boost::condition_variable CConditionVariable
Definition: sync.h:84
void Release()
Definition: sync.h:238
~CSemaphoreGrant()
Definition: sync.h:272
void MoveTo(CSemaphoreGrant &grant)
Definition: sync.h:253
Definition: init.h:14
boost::unique_lock< Mutex > lock
Definition: sync.h:107
bool fHaveGrant
Definition: sync.h:227
void Enter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:109
CMutexLock< CCriticalSection > CCriticalBlock
Definition: sync.h:163
void unlock() UNLOCK_FUNCTION()
Definition: sync.h:63
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
Definition: sync.h:68
void lock() EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:58
CSemaphore * sem
Definition: sync.h:226
bool try_wait()
Definition: sync.h:203
#define UNLOCK_FUNCTION(...)
Definition: threadsafety.h:47
bool TryAcquire()
Definition: sync.h:246
~CMutexLock() UNLOCK_FUNCTION()
Definition: sync.h:151
CSemaphoreGrant(CSemaphore &sema, bool fTry=false)
Definition: sync.h:264
AnnotatedMixin< boost::mutex > CWaitableCriticalSection
Definition: sync.h:81
static void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, void *cs)
Definition: sync.h:94
void wait()
Definition: sync.h:194
static void EnterCritical(const char *pszName, const char *pszFile, int nLine, void *cs, bool fTry=false)
Definition: sync.h:92
static void LeaveCritical()
Definition: sync.h:93
boost::condition_variable condition
Definition: sync.h:187
CSemaphore(int init)
Definition: sync.h:192
#define LOCKABLE
Definition: threadsafety.h:35
CSemaphoreGrant()
Definition: sync.h:262
#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
Definition: threadsafety.h:45
#define SCOPED_LOCKABLE
Definition: threadsafety.h:36
int value
Definition: sync.h:189
boost::mutex mutex
Definition: sync.h:188
AnnotatedMixin< boost::recursive_mutex > CCriticalSection
Definition: sync.h:78
void post()
Definition: sync.h:212
CMutexLock(Mutex &mutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(mutexIn)
Definition: sync.h:132
bool TryEnter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:122
CMutexLock(Mutex *pmutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
Definition: sync.h:140