/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE Versions 3.13.7 * and higher are distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. \*************************************************************************/ #ifndef epicsGuardh #define epicsGuardh #ifndef assert // allow use of epicsAssert.h # include #endif /* * Revision-Id: anj@aps.anl.gov-20101005192737-disfz3vs0f3fiixd * * Author: Jeffrey O. Hill * */ template < class T > class epicsGuardRelease; // Automatically applies and releases the mutex. // This class is also useful in situations where // C++ exceptions are possible. template < class T > class epicsGuard { public: epicsGuard ( T & ); void assertIdenticalMutex ( const T & ) const; ~epicsGuard (); private: T * _pTargetMutex; epicsGuard ( const epicsGuard & ); epicsGuard & operator = ( const epicsGuard & ); friend class epicsGuardRelease < T >; }; // Automatically releases and reapplies the mutex. // 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; T * _pTargetMutex; epicsGuardRelease ( const epicsGuardRelease & ); epicsGuardRelease & operator = ( const epicsGuardRelease & ); }; // same interface as epicsMutex class epicsMutexNOOP { public: void lock (); bool tryLock (); void unlock (); void show ( unsigned level ) const; }; template < class T > inline epicsGuard < T > :: epicsGuard ( T & mutexIn ) : _pTargetMutex ( & mutexIn ) { _pTargetMutex->lock (); } template < class T > inline epicsGuard < T > :: ~epicsGuard () { _pTargetMutex->unlock (); } template < class T > inline void epicsGuard < T > :: assertIdenticalMutex ( const T & mutexToVerify ) const { assert ( _pTargetMutex == & mutexToVerify ); } template < class T > inline epicsGuardRelease < T > :: epicsGuardRelease ( epicsGuard & guardIn ) : _guard ( guardIn ), _pTargetMutex ( guardIn._pTargetMutex ) { // 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 () { _pTargetMutex->lock (); _guard._pTargetMutex = _pTargetMutex; } inline void epicsMutexNOOP::lock () {} inline bool epicsMutexNOOP::tryLock () { return true; } inline void epicsMutexNOOP::unlock () {} inline void epicsMutexNOOP::show ( unsigned ) const {} #endif // epicsGuardh