|
|
@ -221,31 +221,17 @@ std::string FormatFullVersion(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Wrapper to automatically initialize critical sections
|
|
|
|
// Wrapper to automatically initialize mutex
|
|
|
|
class CCriticalSection |
|
|
|
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: |
|
|
|
protected: |
|
|
|
boost::interprocess::interprocess_recursive_mutex mutex; |
|
|
|
boost::interprocess::interprocess_recursive_mutex mutex; |
|
|
|
public: |
|
|
|
public: |
|
|
|
explicit CCriticalSection() { } |
|
|
|
explicit CCriticalSection() { } |
|
|
|
~CCriticalSection() { } |
|
|
|
~CCriticalSection() { } |
|
|
|
void Enter() { mutex.lock(); } |
|
|
|
void Enter(const char* pszName, const char* pszFile, int nLine); |
|
|
|
void Leave() { mutex.unlock(); } |
|
|
|
void Leave(); |
|
|
|
bool TryEnter() { return mutex.try_lock(); } |
|
|
|
bool TryEnter(const char* pszName, const char* pszFile, int nLine); |
|
|
|
#endif |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
const char* pszFile; |
|
|
|
|
|
|
|
int nLine; |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// Automatically leave critical section when leaving block, needed for exception safety
|
|
|
|
// Automatically leave critical section when leaving block, needed for exception safety
|
|
|
@ -253,9 +239,17 @@ class CCriticalBlock |
|
|
|
{ |
|
|
|
{ |
|
|
|
protected: |
|
|
|
protected: |
|
|
|
CCriticalSection* pcs; |
|
|
|
CCriticalSection* pcs; |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; pcs->Enter(); } |
|
|
|
CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) |
|
|
|
~CCriticalBlock() { pcs->Leave(); } |
|
|
|
{ |
|
|
|
|
|
|
|
pcs = &csIn; |
|
|
|
|
|
|
|
pcs->Enter(pszName, pszFile, nLine); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
~CCriticalBlock() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pcs->Leave(); |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
// WARNING: This will catch continue and break!
|
|
|
|
// WARNING: This will catch continue and break!
|
|
|
@ -263,22 +257,32 @@ public: |
|
|
|
// I'd rather be careful than suffer the other more error prone syntax.
|
|
|
|
// I'd rather be careful than suffer the other more error prone syntax.
|
|
|
|
// The compiler will optimise away all this loop junk.
|
|
|
|
// The compiler will optimise away all this loop junk.
|
|
|
|
#define CRITICAL_BLOCK(cs) \ |
|
|
|
#define CRITICAL_BLOCK(cs) \ |
|
|
|
for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \ |
|
|
|
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 (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false) |
|
|
|
|
|
|
|
|
|
|
|
class CTryCriticalBlock |
|
|
|
class CTryCriticalBlock |
|
|
|
{ |
|
|
|
{ |
|
|
|
protected: |
|
|
|
protected: |
|
|
|
CCriticalSection* pcs; |
|
|
|
CCriticalSection* pcs; |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
CTryCriticalBlock(CCriticalSection& csIn) { pcs = (csIn.TryEnter() ? &csIn : NULL); } |
|
|
|
CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine) |
|
|
|
~CTryCriticalBlock() { if (pcs) pcs->Leave(); } |
|
|
|
{ |
|
|
|
|
|
|
|
pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
~CTryCriticalBlock() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (pcs) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pcs->Leave(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
bool Entered() { return pcs != NULL; } |
|
|
|
bool Entered() { return pcs != NULL; } |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
#define TRY_CRITICAL_BLOCK(cs) \ |
|
|
|
#define TRY_CRITICAL_BLOCK(cs) \ |
|
|
|
for (bool fcriticalblockonce=true; fcriticalblockonce; assert("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce), fcriticalblockonce=false) \ |
|
|
|
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 (CTryCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()); fcriticalblockonce=false) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|