Changeset View
Changeset View
Standalone View
Standalone View
src/sync.h
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2016 The Bitcoin Core developers | // Copyright (c) 2009-2016 The Bitcoin Core developers | ||||
// Distributed under the MIT software license, see the accompanying | // Distributed under the MIT software license, see the accompanying | ||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
#ifndef BITCOIN_SYNC_H | #ifndef BITCOIN_SYNC_H | ||||
#define BITCOIN_SYNC_H | #define BITCOIN_SYNC_H | ||||
#include "threadsafety.h" | #include "threadsafety.h" | ||||
#include <boost/thread/condition_variable.hpp> | #include <boost/thread/condition_variable.hpp> | ||||
#include <boost/thread/mutex.hpp> | #include <boost/thread/mutex.hpp> | ||||
#include <boost/thread/recursive_mutex.hpp> | #include <condition_variable> | ||||
#include <mutex> | |||||
#include <thread> | |||||
///////////////////////////////////////////////// | ///////////////////////////////////////////////// | ||||
// // | // // | ||||
// THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE // | // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE // | ||||
// // | // // | ||||
///////////////////////////////////////////////// | ///////////////////////////////////////////////// | ||||
/* | /* | ||||
CCriticalSection mutex; | CCriticalSection mutex; | ||||
boost::recursive_mutex mutex; | std::recursive_mutex mutex; | ||||
LOCK(mutex); | LOCK(mutex); | ||||
boost::unique_lock<boost::recursive_mutex> criticalblock(mutex); | std::unique_lock<std::recursive_mutex> criticalblock(mutex); | ||||
LOCK2(mutex1, mutex2); | LOCK2(mutex1, mutex2); | ||||
boost::unique_lock<boost::recursive_mutex> criticalblock1(mutex1); | std::unique_lock<std::recursive_mutex> criticalblock1(mutex1); | ||||
boost::unique_lock<boost::recursive_mutex> criticalblock2(mutex2); | std::unique_lock<std::recursive_mutex> criticalblock2(mutex2); | ||||
TRY_LOCK(mutex, name); | TRY_LOCK(mutex, name); | ||||
boost::unique_lock<boost::recursive_mutex> name(mutex, | std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t); | ||||
boost::try_to_lock_t); | |||||
ENTER_CRITICAL_SECTION(mutex); // no RAII | ENTER_CRITICAL_SECTION(mutex); // no RAII | ||||
mutex.lock(); | mutex.lock(); | ||||
LEAVE_CRITICAL_SECTION(mutex); // no RAII | LEAVE_CRITICAL_SECTION(mutex); // no RAII | ||||
mutex.unlock(); | mutex.unlock(); | ||||
*/ | */ | ||||
Show All 33 Lines | |||||
static inline void AssertLockHeldInternal(const char *pszName, | static inline void AssertLockHeldInternal(const char *pszName, | ||||
const char *pszFile, int nLine, | const char *pszFile, int nLine, | ||||
void *cs) {} | void *cs) {} | ||||
static inline void DeleteLock(void *cs) {} | static inline void DeleteLock(void *cs) {} | ||||
#endif | #endif | ||||
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) | #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) | ||||
/** | /** | ||||
* Wrapped boost mutex: supports recursive locking, but no waiting | * Wrapped mutex: supports recursive locking, but no waiting | ||||
* TODO: We should move away from using the recursive lock by default. | * TODO: We should move away from using the recursive lock by default. | ||||
*/ | */ | ||||
class CCriticalSection : public AnnotatedMixin<boost::recursive_mutex> { | class CCriticalSection : public AnnotatedMixin<std::recursive_mutex> { | ||||
public: | public: | ||||
~CCriticalSection() { DeleteLock((void *)this); } | ~CCriticalSection() { DeleteLock((void *)this); } | ||||
}; | }; | ||||
/** Wrapped boost mutex: supports waiting but not recursive locking */ | /** Wrapped mutex: supports waiting but not recursive locking */ | ||||
typedef AnnotatedMixin<boost::mutex> CWaitableCriticalSection; | typedef AnnotatedMixin<std::mutex> CWaitableCriticalSection; | ||||
/** Just a typedef for boost::condition_variable, can be wrapped later if | /** | ||||
* desired */ | * Just a typedef for std::condition_variable, can be wrapped later if desired. | ||||
typedef boost::condition_variable CConditionVariable; | */ | ||||
typedef std::condition_variable CConditionVariable; | |||||
/** | |||||
* Just a typedef for std::unique_lock, can be wrapped later if desired. | |||||
*/ | |||||
typedef std::unique_lock<std::mutex> WaitableLock; | |||||
#ifdef DEBUG_LOCKCONTENTION | #ifdef DEBUG_LOCKCONTENTION | ||||
void PrintLockContention(const char *pszName, const char *pszFile, int nLine); | void PrintLockContention(const char *pszName, const char *pszFile, int nLine); | ||||
#endif | #endif | ||||
/** Wrapper around boost::unique_lock<Mutex> */ | /** Wrapper around std::unique_lock<CCriticalSection> */ | ||||
template <typename Mutex> class SCOPED_LOCKABLE CMutexLock { | class SCOPED_LOCKABLE CCriticalBlock { | ||||
private: | private: | ||||
boost::unique_lock<Mutex> lock; | std::unique_lock<CCriticalSection> lock; | ||||
void Enter(const char *pszName, const char *pszFile, int nLine) { | void Enter(const char *pszName, const char *pszFile, int nLine) { | ||||
EnterCritical(pszName, pszFile, nLine, (void *)(lock.mutex())); | EnterCritical(pszName, pszFile, nLine, (void *)(lock.mutex())); | ||||
#ifdef DEBUG_LOCKCONTENTION | #ifdef DEBUG_LOCKCONTENTION | ||||
if (!lock.try_lock()) { | if (!lock.try_lock()) { | ||||
PrintLockContention(pszName, pszFile, nLine); | PrintLockContention(pszName, pszFile, nLine); | ||||
#endif | #endif | ||||
lock.lock(); | lock.lock(); | ||||
#ifdef DEBUG_LOCKCONTENTION | #ifdef DEBUG_LOCKCONTENTION | ||||
} | } | ||||
#endif | #endif | ||||
} | } | ||||
bool TryEnter(const char *pszName, const char *pszFile, int nLine) { | bool TryEnter(const char *pszName, const char *pszFile, int nLine) { | ||||
EnterCritical(pszName, pszFile, nLine, (void *)(lock.mutex()), true); | EnterCritical(pszName, pszFile, nLine, (void *)(lock.mutex()), true); | ||||
lock.try_lock(); | lock.try_lock(); | ||||
if (!lock.owns_lock()) LeaveCritical(); | if (!lock.owns_lock()) LeaveCritical(); | ||||
return lock.owns_lock(); | return lock.owns_lock(); | ||||
} | } | ||||
public: | public: | ||||
CMutexLock(Mutex &mutexIn, const char *pszName, const char *pszFile, | CCriticalBlock(CCriticalSection &mutexIn, const char *pszName, | ||||
int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) | const char *pszFile, int nLine, bool fTry = false) | ||||
: lock(mutexIn, boost::defer_lock) { | EXCLUSIVE_LOCK_FUNCTION(mutexIn) | ||||
: lock(mutexIn, std::defer_lock) { | |||||
if (fTry) | if (fTry) | ||||
TryEnter(pszName, pszFile, nLine); | TryEnter(pszName, pszFile, nLine); | ||||
else | else | ||||
Enter(pszName, pszFile, nLine); | Enter(pszName, pszFile, nLine); | ||||
} | } | ||||
CMutexLock(Mutex *pmutexIn, const char *pszName, const char *pszFile, | CCriticalBlock(CCriticalSection *pmutexIn, const char *pszName, | ||||
int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn) { | const char *pszFile, int nLine, bool fTry = false) | ||||
EXCLUSIVE_LOCK_FUNCTION(pmutexIn) { | |||||
if (!pmutexIn) return; | if (!pmutexIn) return; | ||||
lock = boost::unique_lock<Mutex>(*pmutexIn, boost::defer_lock); | lock = std::unique_lock<CCriticalSection>(*pmutexIn, std::defer_lock); | ||||
if (fTry) | if (fTry) | ||||
TryEnter(pszName, pszFile, nLine); | TryEnter(pszName, pszFile, nLine); | ||||
else | else | ||||
Enter(pszName, pszFile, nLine); | Enter(pszName, pszFile, nLine); | ||||
} | } | ||||
~CMutexLock() UNLOCK_FUNCTION() { | ~CCriticalBlock() UNLOCK_FUNCTION() { | ||||
if (lock.owns_lock()) LeaveCritical(); | if (lock.owns_lock()) LeaveCritical(); | ||||
} | } | ||||
operator bool() { return lock.owns_lock(); } | operator bool() { return lock.owns_lock(); } | ||||
}; | }; | ||||
typedef CMutexLock<CCriticalSection> CCriticalBlock; | |||||
#define PASTE(x, y) x##y | #define PASTE(x, y) x##y | ||||
#define PASTE2(x, y) PASTE(x, y) | #define PASTE2(x, y) PASTE(x, y) | ||||
#define LOCK(cs) \ | #define LOCK(cs) \ | ||||
CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, \ | CCriticalBlock PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, \ | ||||
__LINE__) | __LINE__) | ||||
#define LOCK2(cs1, cs2) \ | #define LOCK2(cs1, cs2) \ | ||||
CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), \ | CCriticalBlock criticalblock1(cs1, #cs1, __FILE__, __LINE__), \ | ||||
▲ Show 20 Lines • Show All 96 Lines • Show Last 20 Lines |