Update CMakeLists.txt - play with openssl
[novacoin.git] / src / sync.h
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 <mutex>
9 #include <condition_variable>
10
11 /** Wrapped boost mutex: supports recursive locking, but no waiting  */
12 typedef std::recursive_mutex CCriticalSection;
13
14 /** Wrapped boost mutex: supports waiting but not recursive locking */
15 typedef std::mutex CWaitableCriticalSection;
16
17 #ifdef DEBUG_LOCKORDER
18 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
19 void LeaveCritical();
20 #else
21 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
22 void static inline LeaveCritical() {}
23 #endif
24
25 #ifdef DEBUG_LOCKCONTENTION
26 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
27 #endif
28
29 /** Wrapper around std::unique_lock<Mutex> */
30 template<typename Mutex>
31 class CMutexLock
32 {
33 private:
34     std::unique_lock<Mutex> lock;
35 public:
36
37     void Enter(const char* pszName, const char* pszFile, int nLine)
38     {
39         if (!lock.owns_lock())
40         {
41             EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
42 #ifdef DEBUG_LOCKCONTENTION
43             if (!lock.try_lock())
44             {
45                 PrintLockContention(pszName, pszFile, nLine);
46 #endif
47             lock.lock();
48 #ifdef DEBUG_LOCKCONTENTION
49             }
50 #endif
51         }
52     }
53
54     void Leave()
55     {
56         if (lock.owns_lock())
57         {
58             lock.unlock();
59             LeaveCritical();
60         }
61     }
62
63     bool TryEnter(const char* pszName, const char* pszFile, int nLine)
64     {
65         if (!lock.owns_lock())
66         {
67             EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
68             if (lock.try_lock())
69                 return true;
70             LeaveCritical();
71         }
72         return false;
73     }
74
75     CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, std::defer_lock)
76     {
77         if (fTry)
78             TryEnter(pszName, pszFile, nLine);
79         else
80             Enter(pszName, pszFile, nLine);
81     }
82
83     ~CMutexLock()
84     {
85         if (lock.owns_lock())
86             LeaveCritical();
87     }
88
89     operator bool() const
90     {
91         return lock.owns_lock();
92     }
93
94     std::unique_lock<Mutex> &GetLock()
95     {
96         return lock;
97     }
98 };
99
100 typedef CMutexLock<CCriticalSection> CCriticalBlock;
101
102 #define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
103 #define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
104 #define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
105
106 #define ENTER_CRITICAL_SECTION(cs) \
107     { \
108         EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
109         (cs).lock(); \
110     }
111
112 #define LEAVE_CRITICAL_SECTION(cs) \
113     { \
114         (cs).unlock(); \
115         LeaveCritical(); \
116     }
117
118 class CSemaphore
119 {
120 private:
121     std::condition_variable condition;
122     std::mutex mutex;
123     int value;
124
125 public:
126     explicit CSemaphore(int init) : value(init) {}
127
128     void wait() {
129         //std::unique_lock<std::mutex> lock(mutex);
130         //while (value < 1) {
131         //    condition.wait(lock);
132         //}
133         //value--;
134         std::unique_lock<std::mutex> lock(mutex);
135         condition.wait(lock, [&]() { return value >= 1; });
136         value--;
137     }
138
139     bool try_wait() {
140         std::unique_lock<std::mutex> lock(mutex);
141         if (value < 1)
142             return false;
143         value--;
144         return true;
145     }
146
147     void post() {
148         {
149             std::unique_lock<std::mutex> lock(mutex);
150             value++;
151         }
152         condition.notify_one();
153     }
154 };
155
156 /** RAII-style semaphore lock */
157 class CSemaphoreGrant
158 {
159 private:
160     CSemaphore *sem;
161     bool fHaveGrant;
162
163 public:
164     void Acquire() {
165         if (!fHaveGrant) {
166             sem->wait();
167             fHaveGrant = true;
168         }
169     }
170
171     void Release() {
172         if (fHaveGrant) {
173             sem->post();
174             fHaveGrant = false;
175         }
176     }
177
178     bool TryAcquire() {
179         if (!fHaveGrant && sem->try_wait())
180             fHaveGrant = true;
181         return fHaveGrant;
182     }
183
184     void MoveTo(CSemaphoreGrant &grant) {
185         grant.Release();
186         grant.sem = sem;
187         grant.fHaveGrant = fHaveGrant;
188         sem = nullptr;
189         fHaveGrant = false;
190     }
191
192     CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
193
194     CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) {
195         if (fTry)
196             TryAcquire();
197         else
198             Acquire();
199     }
200
201     ~CSemaphoreGrant() {
202         Release();
203     }
204
205     operator bool() const {
206         return fHaveGrant;
207     }
208 };
209 #endif