From f306c39e6edf4f800563fc63592d4e0d75bace3b Mon Sep 17 00:00:00 2001 From: rich_sposato Date: Mon, 2 Apr 2012 06:05:04 +0000 Subject: [PATCH] Overloaded functions for volatile to make better use of Memento and Loki::Checker. git-svn-id: svn://svn.code.sf.net/p/loki-lib/code/trunk@1180 7ec92016-0320-0410-acc4-a06ded1c099a --- include/loki/LevelMutex.h | 22 ++++++++++---- src/LevelMutex.cpp | 64 +++++++++++++++++++++++++++------------ 2 files changed, 60 insertions(+), 26 deletions(-) diff --git a/include/loki/LevelMutex.h b/include/loki/LevelMutex.h index 09c4ccb..7a21d47 100644 --- a/include/loki/LevelMutex.h +++ b/include/loki/LevelMutex.h @@ -272,11 +272,15 @@ protected: { public: - explicit Memento( const volatile LevelMutexInfo & mutex ); + explicit Memento( const LevelMutexInfo & mutex ); - bool operator == ( const volatile LevelMutexInfo & mutex ) const; + bool operator == ( const LevelMutexInfo & mutex ) const; private: + + /// Copy-assignment operator is not implemented. + Memento & operator = ( const Memento & ); + /// Level of this mutex. const unsigned int m_level; @@ -295,7 +299,7 @@ protected: exception. The checkers only get used in debug builds, and get optimized away in release builds. */ - typedef ::Loki::CheckFor< volatile LevelMutexInfo, Memento > CheckFor; + typedef ::Loki::CheckFor< const LevelMutexInfo, Memento > CheckFor; /** @class MutexUndoer Undoes actions by MultiLock if an exception occurs. It keeps track of @@ -362,13 +366,13 @@ protected: /** Returns true if no class invariant broken, otherwise asserts. This function only gets called in debug builds. */ - bool IsValid( void ) const; + bool IsValid2( void ) const; /// Returns true if all pre-conditions for PostLock function are valid. - bool PostLockValidator( void ) const volatile; + bool PostLockValidator( void ) const; /// Returns true if all pre-conditions for PreUnlock function are valid. - bool PreUnlockValidator( void ) const volatile; + bool PreUnlockValidator( void ) const; private: @@ -395,16 +399,22 @@ private: /// Called only by MultiUnlock to unlock each particular mutex within a container. virtual MutexErrors::Type UnlockThis( void ) volatile = 0; + void PostLock( void ); + /** The actual implementation of IsLockedByCurrentThread. This does not do any invariant checking because the functions which call it already have. */ bool IsLockedByCurrentThreadImpl( void ) const volatile; + bool IsLockedByCurrentThreadImpl( void ) const; + /** Does just the opposite of IsLockedByCurrentThread. Called as a post-condition check by another function. */ bool IsNotLockedByCurrentThread( void ) const volatile; + bool IsNotLockedByCurrentThread( void ) const; + /// Pointer to singly-linked list of mutexes locked by the current thread. static LOKI_THREAD_LOCAL volatile LevelMutexInfo * s_currentMutex; diff --git a/src/LevelMutex.cpp b/src/LevelMutex.cpp index 150f371..7e68057 100644 --- a/src/LevelMutex.cpp +++ b/src/LevelMutex.cpp @@ -232,7 +232,7 @@ MutexErrors::Type DoMutexesMatchContainer( const LevelMutexInfo::MutexContainer // ---------------------------------------------------------------------------- -LevelMutexInfo::Memento::Memento( const volatile LevelMutexInfo & mutex ) : +LevelMutexInfo::Memento::Memento( const LevelMutexInfo & mutex ) : m_level( mutex.m_level ), m_count( mutex.m_count ), m_previous( mutex.m_previous ), @@ -243,7 +243,7 @@ LevelMutexInfo::Memento::Memento( const volatile LevelMutexInfo & mutex ) : // ---------------------------------------------------------------------------- -bool LevelMutexInfo::Memento::operator == ( const volatile LevelMutexInfo & mutex ) const +bool LevelMutexInfo::Memento::operator == ( const LevelMutexInfo & mutex ) const { assert( this != nullptr ); @@ -593,6 +593,14 @@ LevelMutexInfo::~LevelMutexInfo( void ) // ---------------------------------------------------------------------------- bool LevelMutexInfo::IsValid( void ) const volatile +{ + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + return pThis->IsValid2(); +} + +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::IsValid2( void ) const { assert( nullptr != this ); assert( LevelMutexInfo::UnlockedLevel != m_level ); @@ -604,14 +612,6 @@ bool LevelMutexInfo::IsValid( void ) const volatile // ---------------------------------------------------------------------------- -bool LevelMutexInfo::IsValid( void ) const -{ - const volatile LevelMutexInfo * pThis = const_cast< const volatile LevelMutexInfo * >( this ); - return pThis->IsValid(); -} - -// ---------------------------------------------------------------------------- - void LevelMutexInfo::IncrementCount( void ) volatile { assert( IsValid() ); @@ -636,7 +636,8 @@ bool LevelMutexInfo::IsLockedByCurrentThread( void ) const volatile // gets called by various functions that are called to clean up after an exception // is thrown LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) return IsLockedByCurrentThreadImpl(); @@ -645,6 +646,14 @@ bool LevelMutexInfo::IsLockedByCurrentThread( void ) const volatile // ---------------------------------------------------------------------------- bool LevelMutexInfo::IsLockedByCurrentThreadImpl( void ) const volatile +{ + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + return pThis->IsLockedByCurrentThreadImpl(); +} + +// ---------------------------------------------------------------------------- + +bool LevelMutexInfo::IsLockedByCurrentThreadImpl( void ) const { if ( !IsLocked() ) return false; @@ -681,7 +690,8 @@ bool LevelMutexInfo::IsNotLockedByCurrentThread( void ) const volatile bool LevelMutexInfo::IsRecentLock( void ) const volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrowOrChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -705,7 +715,8 @@ bool LevelMutexInfo::IsRecentLock( void ) const volatile bool LevelMutexInfo::IsRecentLock( std::size_t count ) const volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrowOrChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -728,7 +739,8 @@ bool LevelMutexInfo::IsRecentLock( std::size_t count ) const volatile bool LevelMutexInfo::IsLockedByAnotherThread( void ) const volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrowOrChange checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrowOrChange checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -743,7 +755,7 @@ bool LevelMutexInfo::IsLockedByAnotherThread( void ) const volatile // ---------------------------------------------------------------------------- -bool LevelMutexInfo::PostLockValidator( void ) const volatile +bool LevelMutexInfo::PostLockValidator( void ) const { assert( 0 == m_count ); assert( nullptr == m_previous ); @@ -756,9 +768,18 @@ bool LevelMutexInfo::PostLockValidator( void ) const volatile // ---------------------------------------------------------------------------- void LevelMutexInfo::PostLock( void ) volatile +{ + LevelMutexInfo * pThis = const_cast< LevelMutexInfo * >( this ); + pThis->PostLock(); +} + +// ---------------------------------------------------------------------------- + +void LevelMutexInfo::PostLock( void ) { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid, + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrow checker( pThis, &LevelMutexInfo::IsValid2, &LevelMutexInfo::PostLockValidator, &LevelMutexInfo::IsLockedByCurrentThreadImpl ); (void)checker; ) @@ -775,7 +796,7 @@ void LevelMutexInfo::PostLock( void ) volatile // ---------------------------------------------------------------------------- -bool LevelMutexInfo::PreUnlockValidator( void ) const volatile +bool LevelMutexInfo::PreUnlockValidator( void ) const { assert( 1 == m_count ); assert( nullptr != s_currentMutex ); @@ -790,9 +811,10 @@ bool LevelMutexInfo::PreUnlockValidator( void ) const volatile void LevelMutexInfo::PreUnlock( void ) volatile { LOKI_MUTEX_DEBUG_CODE( + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); // This must use CheckFor::Invariants instead of CheckFor::NoThrow because the // function gets called when MultiLock has to clean up after an exception. - CheckFor::Invariants checker( this, &LevelMutexInfo::IsValid, + CheckFor::Invariants checker( pThis, &LevelMutexInfo::IsValid2, &LevelMutexInfo::PreUnlockValidator, &LevelMutexInfo::IsNotLockedByCurrentThread ); (void)checker; ) @@ -812,7 +834,8 @@ void LevelMutexInfo::PreUnlock( void ) volatile MutexErrors::Type LevelMutexInfo::PreLockCheck( bool forTryLock ) volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrow checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; ) @@ -849,7 +872,8 @@ MutexErrors::Type LevelMutexInfo::PreLockCheck( bool forTryLock ) volatile MutexErrors::Type LevelMutexInfo::PreUnlockCheck( void ) volatile { LOKI_MUTEX_DEBUG_CODE( - CheckFor::NoThrow checker( this, &LevelMutexInfo::IsValid ); + const LevelMutexInfo * pThis = const_cast< const LevelMutexInfo * >( this ); + CheckFor::NoThrow checker( pThis, &LevelMutexInfo::IsValid2 ); (void)checker; )