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