Changeset View
Changeset View
Standalone View
Standalone View
src/sync.h
Show First 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | |||||
/** | /** | ||||
* Wrapped 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. | ||||
*/ | */ | ||||
typedef AnnotatedMixin<std::recursive_mutex> CCriticalSection; | typedef AnnotatedMixin<std::recursive_mutex> CCriticalSection; | ||||
/** Wrapped mutex: supports waiting but not recursive locking */ | /** Wrapped mutex: supports waiting but not recursive locking */ | ||||
typedef AnnotatedMixin<std::mutex> CWaitableCriticalSection; | typedef AnnotatedMixin<std::mutex> Mutex; | ||||
/** | |||||
* Just a typedef for std::condition_variable, can be wrapped later if desired. | |||||
*/ | |||||
typedef std::condition_variable CConditionVariable; | |||||
#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 std::unique_lock style lock for Mutex. */ | /** Wrapper around std::unique_lock style lock for Mutex. */ | ||||
template <typename Mutex, typename Base = typename Mutex::UniqueLock> | template <typename Mutex, typename Base = typename Mutex::UniqueLock> | ||||
class SCOPED_LOCKABLE CCriticalBlock : public Base { | class SCOPED_LOCKABLE UniqueLock : public Base { | ||||
private: | private: | ||||
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 *)(Base::mutex())); | EnterCritical(pszName, pszFile, nLine, (void *)(Base::mutex())); | ||||
#ifdef DEBUG_LOCKCONTENTION | #ifdef DEBUG_LOCKCONTENTION | ||||
if (!Base::try_lock()) { | if (!Base::try_lock()) { | ||||
PrintLockContention(pszName, pszFile, nLine); | PrintLockContention(pszName, pszFile, nLine); | ||||
#endif | #endif | ||||
Base::lock(); | Base::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 *)(Base::mutex()), true); | EnterCritical(pszName, pszFile, nLine, (void *)(Base::mutex()), true); | ||||
Base::try_lock(); | Base::try_lock(); | ||||
if (!Base::owns_lock()) LeaveCritical(); | if (!Base::owns_lock()) LeaveCritical(); | ||||
return Base::owns_lock(); | return Base::owns_lock(); | ||||
} | } | ||||
public: | public: | ||||
CCriticalBlock(Mutex &mutexIn, const char *pszName, const char *pszFile, | UniqueLock(Mutex &mutexIn, const char *pszName, const char *pszFile, | ||||
int nLine, bool fTry = false) | int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) | ||||
EXCLUSIVE_LOCK_FUNCTION(mutexIn) | |||||
: Base(mutexIn, std::defer_lock) { | : Base(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); | ||||
} | } | ||||
} | |||||
CCriticalBlock(Mutex *pmutexIn, const char *pszName, const char *pszFile, | UniqueLock(Mutex *pmutexIn, const char *pszName, const char *pszFile, | ||||
int nLine, bool fTry = false) | int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn) { | ||||
EXCLUSIVE_LOCK_FUNCTION(pmutexIn) { | if (!pmutexIn) { | ||||
if (!pmutexIn) return; | return; | ||||
} | |||||
*static_cast<Base *>(this) = Base(*pmutexIn, std::defer_lock); | *static_cast<Base *>(this) = Base(*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); | ||||
} | } | ||||
} | |||||
~CCriticalBlock() UNLOCK_FUNCTION() { | ~UniqueLock() UNLOCK_FUNCTION() { | ||||
if (Base::owns_lock()) LeaveCritical(); | if (Base::owns_lock()) { | ||||
LeaveCritical(); | |||||
} | |||||
} | } | ||||
operator bool() { return Base::owns_lock(); } | operator bool() { return Base::owns_lock(); } | ||||
}; | }; | ||||
template <typename MutexArg> | template <typename MutexArg> | ||||
using DebugLock = CCriticalBlock<typename std::remove_reference< | using DebugLock = UniqueLock<typename std::remove_reference< | ||||
typename std::remove_pointer<MutexArg>::type>::type>; | typename std::remove_pointer<MutexArg>::type>::type>; | ||||
#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) \ | ||||
DebugLock<decltype(cs)> PASTE2(criticalblock, \ | DebugLock<decltype(cs)> PASTE2(criticalblock, \ | ||||
__COUNTER__)(cs, #cs, __FILE__, __LINE__) | __COUNTER__)(cs, #cs, __FILE__, __LINE__) | ||||
▲ Show 20 Lines • Show All 100 Lines • Show Last 20 Lines |