9#ifdef DEBUG_LOCKCONTENTION
17#include <condition_variable>
56template <
typename MutexType>
57void EnterCritical(
const char *pszName,
const char *pszFile,
int nLine,
58 MutexType *
cs,
bool fTry =
false);
61 const char *file,
int line);
62std::string LocksHeld();
63template <
typename MutexType>
66template <
typename MutexType>
77extern bool g_debug_lockorder_abort;
79template <
typename MutexType>
80inline void EnterCritical(
const char *pszName,
const char *pszFile,
int nLine,
81 MutexType *
cs,
bool fTry =
false) {}
84 const char *guardname,
const char *file,
86template <
typename MutexType>
88 int nLine, MutexType *
cs)
90template <
typename MutexType>
112 return PARENT::try_lock();
146#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
163#define AssertLockNotHeld(cs) \
164 AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
167template <
typename Mutex,
typename Base =
typename Mutex::UniqueLock>
170 void Enter(
const char *pszName,
const char *pszFile,
int nLine) {
172#ifdef DEBUG_LOCKCONTENTION
173 if (Base::try_lock()) {
177 strprintf(
"lock contention %s, %s:%d", pszName, pszFile, nLine),
183 bool TryEnter(
const char *pszName,
const char *pszFile,
int nLine) {
185 if (Base::try_lock()) {
195 : Base(mutexIn,
std::defer_lock) {
197 TryEnter(pszName, pszFile, nLine);
199 Enter(pszName, pszFile, nLine);
209 *
static_cast<Base *
>(
this) = Base(*pmutexIn, std::defer_lock);
211 TryEnter(pszName, pszFile, nLine);
213 Enter(pszName, pszFile, nLine);
218 if (Base::owns_lock()) {
223 operator bool() {
return Base::owns_lock(); }
237 const char *_file,
int _line)
238 : lock(_lock), file(_file), line(_line) {
248 EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
265#define REVERSE_LOCK(g) \
266 typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_LOG_NAME( \
267 revlock)(g, #g, __FILE__, __LINE__)
269template <
typename MutexArg>
271 typename std::remove_pointer<MutexArg>::type>::type>;
307 DebugLock<decltype(cs)> UNIQUE_LOG_NAME(criticalblock)( \
308 MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
309#define LOCK2(cs1, cs2) \
310 DebugLock<decltype(cs1)> criticalblock1(MaybeCheckNotHeld(cs1), #cs1, \
311 __FILE__, __LINE__); \
312 DebugLock<decltype(cs2)> criticalblock2(MaybeCheckNotHeld(cs2), #cs2, \
314#define TRY_LOCK(cs, name) \
315 DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, \
317#define WAIT_LOCK(cs, name) \
318 DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
320#define ENTER_CRITICAL_SECTION(cs) \
322 EnterCritical(#cs, __FILE__, __LINE__, &cs); \
326#define LEAVE_CRITICAL_SECTION(cs) \
328 std::string lockname; \
329 CheckLastCritical((void *)(&cs), lockname, #cs, __FILE__, __LINE__); \
357#define WITH_LOCK(cs, code) \
358 (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { \
373 std::unique_lock<std::mutex> lock(
mutex);
379 std::lock_guard<std::mutex> lock(
mutex);
389 std::lock_guard<std::mutex> lock(
mutex);
Template mixin that adds -Wthread-safety locking annotations and lock order checking to a subset of t...
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
void unlock() UNLOCK_FUNCTION()
void lock() EXCLUSIVE_LOCK_FUNCTION()
RAII-style semaphore lock.
CSemaphoreGrant(CSemaphore &sema, bool fTry=false)
void MoveTo(CSemaphoreGrant &grant)
std::condition_variable condition
Different type to mark Mutex at global scope.
An RAII-style reverse lock.
reverse_lock(reverse_lock const &)
reverse_lock & operator=(reverse_lock const &)
reverse_lock(UniqueLock &_lock, const char *_guardname, const char *_file, int _line)
Wrapper around std::unique_lock style lock for Mutex.
bool TryEnter(const char *pszName, const char *pszFile, int nLine)
~UniqueLock() UNLOCK_FUNCTION()
UniqueLock(Mutex &mutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(mutexIn)
void Enter(const char *pszName, const char *pszFile, int nLine)
UniqueLock(Mutex *pmutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
Implement std::hash so RCUPtr can be used as a key for maps or sets.
void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) EXCLUSIVE_LOCKS_REQUIRED(cs)
void AssertLockNotHeldInline(const char *name, const char *file, int line, Mutex *cs) EXCLUSIVE_LOCKS_REQUIRED(!cs)
void EnterCritical(const char *pszName, const char *pszFile, int nLine, MutexType *cs, bool fTry=false)
void DeleteLock(void *cs)
void CheckLastCritical(void *cs, std::string &lockname, const char *guardname, const char *file, int line)
Mutex & MaybeCheckNotHeld(Mutex &cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs)
void AssertLockNotHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) LOCKS_EXCLUDED(cs)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
#define LOCKS_EXCLUDED(...)
#define EXCLUSIVE_LOCK_FUNCTION(...)
#define UNLOCK_FUNCTION(...)
#define LOG_TIME_MICROS_WITH_CATEGORY(end_msg, log_category)