Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
sync.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 The Bitcoin developers
3 // Distributed under the MIT/X11 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 DEFINITON, EXCLUDING DEBUG CODE //
20 // //
22 
23 /*
24 
25 
26 
27 CCriticalSection mutex;
28  boost::recursive_mutex mutex;
29 
30 LOCK(mutex);
31  boost::unique_lock<boost::recursive_mutex> criticalblock(mutex);
32 
33 LOCK2(mutex1, mutex2);
34  boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1);
35  boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2);
36 
37 TRY_LOCK(mutex, name);
38  boost::unique_lock<boost::recursive_mutex> name(mutex, boost::try_to_lock_t);
39 
40 ENTER_CRITICAL_SECTION(mutex); // no RAII
41  mutex.lock();
42 
43 LEAVE_CRITICAL_SECTION(mutex); // no RAII
44  mutex.unlock();
45 
46 
47 
48  */
49 
50 
51 
53 // //
54 // THE ACTUAL IMPLEMENTATION //
55 // //
57 
58 // Template mixin that adds -Wthread-safety locking annotations to a
59 // subset of the mutex API.
60 template <typename PARENT>
62 {
63 public:
65  {
66  PARENT::lock();
67  }
68 
70  {
71  PARENT::unlock();
72  }
73 
75  {
76  return PARENT::try_lock();
77  }
78 };
79 
81 // TODO: We should move away from using the recursive lock by default.
83 
86 
87 #ifdef DEBUG_LOCKORDER
88 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
89 void LeaveCritical();
90 std::string LocksHeld();
91 void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs);
92 #else
93 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
94 void static inline LeaveCritical() {}
95 void static inline AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, void *cs) {}
96 #endif
97 #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
98 
99 #ifdef DEBUG_LOCKCONTENTION
100 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
101 #endif
102 
104 template<typename Mutex>
106 {
107 private:
108  boost::unique_lock<Mutex> lock;
109 
110  void Enter(const char* pszName, const char* pszFile, int nLine)
111  {
112  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
113 #ifdef DEBUG_LOCKCONTENTION
114  if (!lock.try_lock())
115  {
116  PrintLockContention(pszName, pszFile, nLine);
117 #endif
118  lock.lock();
119 #ifdef DEBUG_LOCKCONTENTION
120  }
121 #endif
122  }
123 
124  bool TryEnter(const char* pszName, const char* pszFile, int nLine)
125  {
126  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
127  lock.try_lock();
128  if (!lock.owns_lock())
129  LeaveCritical();
130  return lock.owns_lock();
131  }
132 
133 public:
134  CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
135  {
136  if (fTry)
137  TryEnter(pszName, pszFile, nLine);
138  else
139  Enter(pszName, pszFile, nLine);
140  }
141 
143  {
144  if (lock.owns_lock())
145  LeaveCritical();
146  }
147 
148  operator bool()
149  {
150  return lock.owns_lock();
151  }
152 };
153 
155 
156 #define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
157 #define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
158 #define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
159 
160 #define ENTER_CRITICAL_SECTION(cs) \
161  { \
162  EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
163  (cs).lock(); \
164  }
165 
166 #define LEAVE_CRITICAL_SECTION(cs) \
167  { \
168  (cs).unlock(); \
169  LeaveCritical(); \
170  }
171 
173 {
174 private:
175  boost::condition_variable condition;
176  boost::mutex mutex;
177  int value;
178 
179 public:
180  CSemaphore(int init) : value(init) {}
181 
182  void wait() {
183  boost::unique_lock<boost::mutex> lock(mutex);
184  while (value < 1) {
185  condition.wait(lock);
186  }
187  value--;
188  }
189 
190  bool try_wait() {
191  boost::unique_lock<boost::mutex> lock(mutex);
192  if (value < 1)
193  return false;
194  value--;
195  return true;
196  }
197 
198  void post() {
199  {
200  boost::unique_lock<boost::mutex> lock(mutex);
201  value++;
202  }
203  condition.notify_one();
204  }
205 };
206 
209 {
210 private:
213 
214 public:
215  void Acquire() {
216  if (fHaveGrant)
217  return;
218  sem->wait();
219  fHaveGrant = true;
220  }
221 
222  void Release() {
223  if (!fHaveGrant)
224  return;
225  sem->post();
226  fHaveGrant = false;
227  }
228 
229  bool TryAcquire() {
230  if (!fHaveGrant && sem->try_wait())
231  fHaveGrant = true;
232  return fHaveGrant;
233  }
234 
235  void MoveTo(CSemaphoreGrant &grant) {
236  grant.Release();
237  grant.sem = sem;
238  grant.fHaveGrant = fHaveGrant;
239  sem = NULL;
240  fHaveGrant = false;
241  }
242 
243  CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {}
244 
245  CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) {
246  if (fTry)
247  TryAcquire();
248  else
249  Acquire();
250  }
251 
253  Release();
254  }
255 
256  operator bool() {
257  return fHaveGrant;
258  }
259 };
260 #endif
261 
void MoveTo(CSemaphoreGrant &grant)
Definition: sync.h:235
void unlock() UNLOCK_FUNCTION()
Definition: sync.h:69
#define EXCLUSIVE_LOCK_FUNCTION(...)
Definition: threadsafety.h:43
~CMutexLock()
Definition: sync.h:142
Definition: init.h:13
RAII-style semaphore lock.
Definition: sync.h:208
CMutexLock< CCriticalSection > CCriticalBlock
Definition: sync.h:154
bool try_wait()
Definition: sync.h:190
void lock() EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:64
void Acquire()
Definition: sync.h:215
#define UNLOCK_FUNCTION(...)
Definition: threadsafety.h:47
CSemaphoreGrant(CSemaphore &sema, bool fTry=false)
Definition: sync.h:245
~CSemaphoreGrant()
Definition: sync.h:252
void Enter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:110
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
Definition: sync.h:74
AnnotatedMixin< boost::mutex > CWaitableCriticalSection
Wrapped boost mutex: supports waiting but not recursive locking.
Definition: sync.h:85
static void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, void *cs)
Definition: sync.h:95
CSemaphore * sem
Definition: sync.h:211
int value
Definition: sync.h:177
void Release()
Definition: sync.h:222
static void EnterCritical(const char *pszName, const char *pszFile, int nLine, void *cs, bool fTry=false)
Definition: sync.h:93
Wrapper around boost::unique_lock
Definition: sync.h:105
static void LeaveCritical()
Definition: sync.h:94
CSemaphoreGrant()
Definition: sync.h:243
boost::mutex mutex
Definition: sync.h:176
#define LOCKABLE
Definition: threadsafety.h:35
boost::condition_variable condition
Definition: sync.h:175
void wait()
Definition: sync.h:182
bool TryEnter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:124
#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
Definition: threadsafety.h:45
CSemaphore(int init)
Definition: sync.h:180
AnnotatedMixin< boost::recursive_mutex > CCriticalSection
Wrapped boost mutex: supports recursive locking, but no waiting.
Definition: sync.h:82
void post()
Definition: sync.h:198
CMutexLock(Mutex &mutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false)
Definition: sync.h:134
bool TryAcquire()
Definition: sync.h:229
bool fHaveGrant
Definition: sync.h:212
boost::unique_lock< Mutex > lock
Definition: sync.h:108