aboutsummaryrefslogtreecommitdiff
path: root/src/util.h
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2011-03-29 11:32:16 -0400
committerGavin Andresen <gavinandresen@gmail.com>2011-08-17 10:22:28 -0400
commit865ed8a1e5c587468a40756d46bcbc1c5a12bb06 (patch)
tree178a78d9057931de2a0db1099193efe73da6d6a1 /src/util.h
parentc7286112efe5c9ee7924aa387c8f4280473a72a8 (diff)
downloadbitcoin-865ed8a1e5c587468a40756d46bcbc1c5a12bb06.tar.xz
Compile with DEBUG_LOCKORDER to detect inconsistent lock orderings that can cause deadlocks
Diffstat (limited to 'src/util.h')
-rw-r--r--src/util.h56
1 files changed, 30 insertions, 26 deletions
diff --git a/src/util.h b/src/util.h
index 77f08d7471..1e4ceb2468 100644
--- a/src/util.h
+++ b/src/util.h
@@ -223,31 +223,17 @@ std::string FormatFullVersion();
-// Wrapper to automatically initialize critical sections
+// Wrapper to automatically initialize mutex
class CCriticalSection
{
-#ifdef __WXMSW__
-protected:
- CRITICAL_SECTION cs;
-public:
- explicit CCriticalSection() { InitializeCriticalSection(&cs); }
- ~CCriticalSection() { DeleteCriticalSection(&cs); }
- void Enter() { EnterCriticalSection(&cs); }
- void Leave() { LeaveCriticalSection(&cs); }
- bool TryEnter() { return TryEnterCriticalSection(&cs); }
-#else
protected:
boost::interprocess::interprocess_recursive_mutex mutex;
public:
explicit CCriticalSection() { }
~CCriticalSection() { }
- void Enter() { mutex.lock(); }
- void Leave() { mutex.unlock(); }
- bool TryEnter() { return mutex.try_lock(); }
-#endif
-public:
- const char* pszFile;
- int nLine;
+ void Enter(const char* pszName, const char* pszFile, int nLine);
+ void Leave();
+ bool TryEnter(const char* pszName, const char* pszFile, int nLine);
};
// Automatically leave critical section when leaving block, needed for exception safety
@@ -255,9 +241,17 @@ class CCriticalBlock
{
protected:
CCriticalSection* pcs;
+
public:
- CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; pcs->Enter(); }
- ~CCriticalBlock() { pcs->Leave(); }
+ CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+ {
+ pcs = &csIn;
+ pcs->Enter(pszName, pszFile, nLine);
+ }
+ ~CCriticalBlock()
+ {
+ pcs->Leave();
+ }
};
// WARNING: This will catch continue and break!
@@ -265,22 +259,32 @@ public:
// I'd rather be careful than suffer the other more error prone syntax.
// The compiler will optimise away all this loop junk.
#define CRITICAL_BLOCK(cs) \
- for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \
- for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
+ for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
+ for (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false)
class CTryCriticalBlock
{
protected:
CCriticalSection* pcs;
+
public:
- CTryCriticalBlock(CCriticalSection& csIn) { pcs = (csIn.TryEnter() ? &csIn : NULL); }
- ~CTryCriticalBlock() { if (pcs) pcs->Leave(); }
+ CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+ {
+ pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL);
+ }
+ ~CTryCriticalBlock()
+ {
+ if (pcs)
+ {
+ pcs->Leave();
+ }
+ }
bool Entered() { return pcs != NULL; }
};
#define TRY_CRITICAL_BLOCK(cs) \
- for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \
- for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
+ for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
+ for (CTryCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()); fcriticalblockonce=false)