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.
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>
16 /** Wrapped boost mutex: supports recursive locking, but no waiting */
17 typedef boost::recursive_mutex CCriticalSection;
19 /** Wrapped boost mutex: supports waiting but not recursive locking */
20 typedef boost::mutex CWaitableCriticalSection;
22 #ifdef DEBUG_LOCKORDER
23 void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
26 void static inline EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
27 void static inline LeaveCritical() {}
30 #ifdef DEBUG_LOCKCONTENTION
31 void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
34 /** Wrapper around boost::interprocess::scoped_lock */
35 template<typename Mutex>
39 boost::unique_lock<Mutex> lock;
42 void Enter(const char* pszName, const char* pszFile, int nLine)
44 if (!lock.owns_lock())
46 EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()));
47 #ifdef DEBUG_LOCKCONTENTION
50 PrintLockContention(pszName, pszFile, nLine);
53 #ifdef DEBUG_LOCKCONTENTION
68 bool TryEnter(const char* pszName, const char* pszFile, int nLine)
70 if (!lock.owns_lock())
72 EnterCritical(pszName, pszFile, nLine, (void*)(lock.mutex()), true);
74 if (!lock.owns_lock())
77 return lock.owns_lock();
80 CMutexLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) : lock(mutexIn, boost::defer_lock)
83 TryEnter(pszName, pszFile, nLine);
85 Enter(pszName, pszFile, nLine);
96 return lock.owns_lock();
99 boost::unique_lock<Mutex> &GetLock()
105 typedef CMutexLock<CCriticalSection> CCriticalBlock;
107 #define LOCK(cs) CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__)
108 #define LOCK2(cs1,cs2) CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__),criticalblock2(cs2, #cs2, __FILE__, __LINE__)
109 #define TRY_LOCK(cs,name) CCriticalBlock name(cs, #cs, __FILE__, __LINE__, true)
111 #define ENTER_CRITICAL_SECTION(cs) \
113 EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
117 #define LEAVE_CRITICAL_SECTION(cs) \
126 boost::condition_variable condition;
131 CSemaphore(int init) : value(init) {}
134 boost::unique_lock<boost::mutex> lock(mutex);
136 condition.wait(lock);
142 boost::unique_lock<boost::mutex> lock(mutex);
151 boost::unique_lock<boost::mutex> lock(mutex);
154 condition.notify_one();
158 /** RAII-style semaphore lock */
159 class CSemaphoreGrant
181 if (!fHaveGrant && sem->try_wait())
186 void MoveTo(CSemaphoreGrant &grant) {
189 grant.fHaveGrant = fHaveGrant;
194 CSemaphoreGrant() : sem(NULL), fHaveGrant(false) {}
196 CSemaphoreGrant(CSemaphore &sema, bool fTry = false) : sem(&sema), fHaveGrant(false) {