Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
sync.h
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 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 #ifndef BITCOIN_SYNC_H
6 #define BITCOIN_SYNC_H
7 
8 #include <boost/thread/mutex.hpp>
9 #include <boost/thread/recursive_mutex.hpp>
10 #include <boost/thread/locks.hpp>
11 #include <boost/thread/condition_variable.hpp>
12 #include "threadsafety.h"
13 
14 // Template mixin that adds -Wthread-safety locking annotations to a
15 // subset of the mutex API.
16 template <typename PARENT>
17 class LOCKABLE AnnotatedMixin : public PARENT
18 {
19 public:
21  {
22  PARENT::lock();
23  }
24 
26  {
27  PARENT::unlock();
28  }
29 
31  {
32  return PARENT::try_lock();
33  }
34 };
35 
37 // TODO: We should move away from using the recursive lock by default.
39 
42 
43 #ifdef DEBUG_LOCKORDER
44 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
45 void LeaveCritical();
46 #else
47 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
48 void static inline LeaveCritical() {}
49 #endif
50 
51 #ifdef DEBUG_LOCKCONTENTION
52 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
53 #endif
54 
56 template<typename Mutex>
58 {
59 private:
60  boost::unique_lock<Mutex> lock;
61 
62  void Enter(const char* pszName, const char* pszFile, int nLine)
63  {
64  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
65 #ifdef DEBUG_LOCKCONTENTION
66  if (!lock.try_lock())
67  {
68  PrintLockContention(pszName, pszFile, nLine);
69 #endif
70  lock.lock();
71 #ifdef DEBUG_LOCKCONTENTION
72  }
73 #endif
74  }
75 
76  bool TryEnter(const char* pszName, const char* pszFile, int nLine)
77  {
78  EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
79  lock.try_lock();
80  if (!lock.owns_lock())
81  LeaveCritical();
82  return lock.owns_lock();
83  }
84 
85 public:
86  CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
87  {
88  if (fTry)
89  TryEnter(pszName, pszFile, nLine);
90  else
91  Enter(pszName, pszFile, nLine);
92  }
93 
95  {
96  if (lock.owns_lock())
97  LeaveCritical();
98  }
99 
100  operator bool()
101  {
102  return lock.owns_lock();
103  }
104 };
105 
107 
108 #define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
109 #define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
110 #define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
111 
112 #define ENTER_CRITICAL_SECTION(cs) \
113  { \
114  EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
115  (cs).lock(); \
116  }
117 
118 #define LEAVE_CRITICAL_SECTION(cs) \
119  { \
120  (cs).unlock(); \
121  LeaveCritical(); \
122  }
123 
125 {
126 private:
127  boost::condition_variable condition;
128  boost::mutex mutex;
129  int value;
130 
131 public:
132  CSemaphore(int init) : value(init) {}
133 
134  void wait() {
135  boost::unique_lock<boost::mutex> lock(mutex);
136  while (value < 1) {
137  condition.wait(lock);
138  }
139  value--;
140  }
141 
142  bool try_wait() {
143  boost::unique_lock<boost::mutex> lock(mutex);
144  if (value < 1)
145  return false;
146  value--;
147  return true;
148  }
149 
150  void post() {
151  {
152  boost::unique_lock<boost::mutex> lock(mutex);
153  value++;
154  }
155  condition.notify_one();
156  }
157 };
158 
161 {
162 private:
165 
166 public:
167  void Acquire() {
168  if (fHaveGrant)
169  return;
170  sem->wait();
171  fHaveGrant = true;
172  }
173 
174  void Release() {
175  if (!fHaveGrant)
176  return;
177  sem->post();
178  fHaveGrant = false;
179  }
180 
181  bool TryAcquire() {
182  if (!fHaveGrant && sem->try_wait())
183  fHaveGrant = true;
184  return fHaveGrant;
185  }
186 
187  void MoveTo(CSemaphoreGrant &grant) {
188  grant.Release();
189  grant.sem = sem;
190  grant.fHaveGrant = fHaveGrant;
191  sem = NULL;
192  fHaveGrant = false;
193  }
194 
195  CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {}
196 
197  CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) {
198  if (fTry)
199  TryAcquire();
200  else
201  Acquire();
202  }
203 
205  Release();
206  }
207 
208  operator bool() {
209  return fHaveGrant;
210  }
211 };
212 #endif
213 
void MoveTo(CSemaphoreGrant &grant)
Definition: sync.h:187
void unlock() UNLOCK_FUNCTION()
Definition: sync.h:25
#define EXCLUSIVE_LOCK_FUNCTION(...)
~CMutexLock()
Definition: sync.h:94
Definition: util.cpp:28
#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
RAII-style semaphore lock.
Definition: sync.h:160
CMutexLock< CCriticalSection > CCriticalBlock
Definition: sync.h:106
bool try_wait()
Definition: sync.h:142
void lock() EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:20
void Acquire()
Definition: sync.h:167
CSemaphoreGrant(CSemaphore &sema, bool fTry=false)
Definition: sync.h:197
~CSemaphoreGrant()
Definition: sync.h:204
void Enter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:62
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
Definition: sync.h:30
AnnotatedMixin< boost::mutex > CWaitableCriticalSection
Wrapped boost mutex: supports waiting but not recursive locking.
Definition: sync.h:41
CSemaphore * sem
Definition: sync.h:163
int value
Definition: sync.h:129
void Release()
Definition: sync.h:174
Wrapper around boost::unique_lock
Definition: sync.h:57
CSemaphoreGrant()
Definition: sync.h:195
#define UNLOCK_FUNCTION(...)
boost::mutex mutex
Definition: sync.h:128
#define LOCKABLE
Definition: threadsafety.h:34
boost::condition_variable condition
Definition: sync.h:127
void wait()
Definition: sync.h:134
bool TryEnter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:76
CSemaphore(int init)
Definition: sync.h:132
AnnotatedMixin< boost::recursive_mutex > CCriticalSection
Wrapped boost mutex: supports recursive locking, but no waiting.
Definition: sync.h:38
void post()
Definition: sync.h:150
CMutexLock(Mutex &mutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false)
Definition: sync.h:86
bool TryAcquire()
Definition: sync.h:181
bool fHaveGrant
Definition: sync.h:164
boost::unique_lock< Mutex > lock
Definition: sync.h:60