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.
9 #include <condition_variable>
11 /** Wrapped boost mutex: supports recursive locking, but no waiting */
12 typedef std::recursive_mutex CCriticalSection;
14 /** Wrapped boost mutex: supports waiting but not recursive locking */
15 typedef std::mutex CWaitableCriticalSection;
17 #ifdef DEBUG_LOCKORDER
18 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
21 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
22 void static inline LeaveCritical() {}
25 #ifdef DEBUG_LOCKCONTENTION
26 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
29 /** Wrapper around std::unique_lock<Mutex> */
30 template<typename Mutex>
34 std::unique_lock<Mutex> lock;
37 void Enter(const char* pszName, const char* pszFile, int nLine)
39 if (!lock.owns_lock())
41 EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
42 #ifdef DEBUG_LOCKCONTENTION
45 PrintLockContention(pszName, pszFile, nLine);
48 #ifdef DEBUG_LOCKCONTENTION
63 bool TryEnter(const char* pszName, const char* pszFile, int nLine)
65 if (!lock.owns_lock())
67 EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
69 if (!lock.owns_lock())
72 return lock.owns_lock();
75 CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, std::defer_lock)
78 TryEnter(pszName, pszFile, nLine);
80 Enter(pszName, pszFile, nLine);
91 return lock.owns_lock();
94 std::unique_lock<Mutex> &GetLock()
100 typedef CMutexLock<CCriticalSection> CCriticalBlock;
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)
106 #define ENTER_CRITICAL_SECTION(cs) \
108 EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
112 #define LEAVE_CRITICAL_SECTION(cs) \
121 std::condition_variable condition;
126 explicit CSemaphore(int init) : value(init) {}
129 //std::unique_lock<std::mutex> lock(mutex);
130 //while (value < 1) {
131 // condition.wait(lock);
134 std::unique_lock<std::mutex> lock(mutex);
135 condition.wait(lock, [&]() { return value >= 1; });
140 std::unique_lock<std::mutex> lock(mutex);
149 std::unique_lock<std::mutex> lock(mutex);
152 condition.notify_one();
156 /** RAII-style semaphore lock */
157 class CSemaphoreGrant
179 if (!fHaveGrant && sem->try_wait())
184 void MoveTo(CSemaphoreGrant &grant) {
187 grant.fHaveGrant = fHaveGrant;
192 CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
194 CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) {
205 operator bool() const {