From 3ec09adf208b32f2938c27caf68ceb66cb4d5780 Mon Sep 17 00:00:00 2001 From: Jeff Hill Date: Thu, 11 Jan 2007 22:04:44 +0000 Subject: [PATCH] added code to catch bugs where a guard is used when it is released --- src/libCom/cxxTemplates/epicsGuard.h | 45 +++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/libCom/cxxTemplates/epicsGuard.h b/src/libCom/cxxTemplates/epicsGuard.h index 9726aff89..c60652516 100644 --- a/src/libCom/cxxTemplates/epicsGuard.h +++ b/src/libCom/cxxTemplates/epicsGuard.h @@ -12,7 +12,7 @@ #define epicsGuardh #ifndef assert // allow use of epicsAssert.h -# include +# include #endif /* @@ -25,29 +25,32 @@ template < class T > class epicsGuardRelease; // Automatically applies and releases the mutex. -// This is for use in situations where C++ exceptions are possible. +// This class is also useful in situations where +// C++ exceptions are possible. template < class T > class epicsGuard { public: - epicsGuard ( const epicsGuard & ); epicsGuard ( T & ); void assertIdenticalMutex ( const T & ) const; ~epicsGuard (); private: - T & targetMutex; + T * _pTargetMutex; + epicsGuard ( const epicsGuard & ); epicsGuard & operator = ( const epicsGuard & ); friend class epicsGuardRelease < T >; }; // Automatically releases and reapplies the mutex. -// This is for use in situations where C++ exceptions are possible. +// This class is also useful in situations where +// C++ exceptions are possible. template < class T > class epicsGuardRelease { public: epicsGuardRelease ( epicsGuard < T > & ); ~epicsGuardRelease (); private: - epicsGuard < T > & guard; + epicsGuard < T > & _guard; + T * _pTargetMutex; epicsGuardRelease ( const epicsGuardRelease & ); epicsGuardRelease & operator = ( const epicsGuardRelease & ); }; @@ -63,43 +66,45 @@ public: template < class T > inline epicsGuard < T > :: epicsGuard ( T & mutexIn ) : - targetMutex ( mutexIn ) + _pTargetMutex ( & mutexIn ) { - this->targetMutex.lock (); -} - -template < class T > -epicsGuard < T > :: epicsGuard ( const epicsGuard & guardIn ) : - targetMutex ( guardIn.targetMutex ) -{ - this->targetMutex.lock (); + _pTargetMutex->lock (); } template < class T > inline epicsGuard < T > :: ~epicsGuard () { - this->targetMutex.unlock (); + _pTargetMutex->unlock (); } template < class T > inline void epicsGuard < T > :: assertIdenticalMutex ( const T & mutexToVerify ) const { - assert ( & this->targetMutex == & mutexToVerify ); + assert ( _pTargetMutex == & mutexToVerify ); } template < class T > inline epicsGuardRelease < T > :: epicsGuardRelease ( epicsGuard & guardIn ) : - guard ( guardIn ) + _guard ( guardIn ), + _pTargetMutex ( guardIn._pTargetMutex ) { - this->guard.targetMutex.unlock (); + // Setting the guard's _pTargetMutex to nill will + // allow assertIdenticalMutex to catch situations + // where a guard is being used and it has been + // released, and also situations where ~epicsGuard () + // runs and an epicsGuardRelease is still referencing + // the guard will be detected. + _guard._pTargetMutex = 0; + _pTargetMutex->unlock (); } template < class T > inline epicsGuardRelease < T > :: ~epicsGuardRelease () { - this->guard.targetMutex.lock (); + _pTargetMutex->lock (); + _guard._pTargetMutex = _pTargetMutex; } inline void epicsMutexNOOP::lock () {}