@ -111,7 +111,7 @@ public:
return PARENT : : try_lock ( ) ;
return PARENT : : try_lock ( ) ;
}
}
using UniqueL ock = std : : unique_lock < PARENT > ;
using unique_l ock = std : : unique_lock < PARENT > ;
# ifdef __clang__
# ifdef __clang__
//! For negative capabilities in the Clang Thread Safety Analysis.
//! For negative capabilities in the Clang Thread Safety Analysis.
//! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
//! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
@ -147,11 +147,13 @@ inline void AssertLockNotHeldInline(const char* name, const char* file, int line
inline void AssertLockNotHeldInline ( const char * name , const char * file , int line , GlobalMutex * cs ) LOCKS_EXCLUDED ( cs ) { AssertLockNotHeldInternal ( name , file , line , cs ) ; }
inline void AssertLockNotHeldInline ( const char * name , const char * file , int line , GlobalMutex * cs ) LOCKS_EXCLUDED ( cs ) { AssertLockNotHeldInternal ( name , file , line , cs ) ; }
# define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
# define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
/** Wrapper around std::unique_lock style lock for Mutex . */
/** Wrapper around std::unique_lock style lock for Mutex Type . */
template < typename Mutex , typename Base = typename Mutex : : UniqueLock >
template < typename Mutex Type >
class SCOPED_LOCKABLE UniqueLock : public Base
class SCOPED_LOCKABLE UniqueLock : public MutexType: : unique_lock
{
{
private :
private :
using Base = typename MutexType : : unique_lock ;
void Enter ( const char * pszName , const char * pszFile , int nLine )
void Enter ( const char * pszName , const char * pszFile , int nLine )
{
{
EnterCritical ( pszName , pszFile , nLine , Base : : mutex ( ) ) ;
EnterCritical ( pszName , pszFile , nLine , Base : : mutex ( ) ) ;
@ -173,7 +175,7 @@ private:
}
}
public :
public :
UniqueLock ( Mutex & mutexIn , const char * pszName , const char * pszFile , int nLine , bool fTry = false ) EXCLUSIVE_LOCK_FUNCTION ( mutexIn ) : Base ( mutexIn , std : : defer_lock )
UniqueLock ( Mutex Type & mutexIn , const char * pszName , const char * pszFile , int nLine , bool fTry = false ) EXCLUSIVE_LOCK_FUNCTION ( mutexIn ) : Base ( mutexIn , std : : defer_lock )
{
{
if ( fTry )
if ( fTry )
TryEnter ( pszName , pszFile , nLine ) ;
TryEnter ( pszName , pszFile , nLine ) ;
@ -181,7 +183,7 @@ public:
Enter ( pszName , pszFile , nLine ) ;
Enter ( pszName , pszFile , nLine ) ;
}
}
UniqueLock ( Mutex * pmutexIn , const char * pszName , const char * pszFile , int nLine , bool fTry = false ) EXCLUSIVE_LOCK_FUNCTION ( pmutexIn )
UniqueLock ( Mutex Type * pmutexIn , const char * pszName , const char * pszFile , int nLine , bool fTry = false ) EXCLUSIVE_LOCK_FUNCTION ( pmutexIn )
{
{
if ( ! pmutexIn ) return ;
if ( ! pmutexIn ) return ;
@ -241,29 +243,24 @@ public:
# define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, #g, __FILE__, __LINE__)
# define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, #g, __FILE__, __LINE__)
template < typename MutexArg >
using DebugLock = UniqueLock < typename std : : remove_reference < typename std : : remove_pointer < MutexArg > : : type > : : type > ;
// When locking a Mutex, require negative capability to ensure the lock
// When locking a Mutex, require negative capability to ensure the lock
// is not already held
// is not already held
inline Mutex & MaybeCheckNotHeld ( Mutex & cs ) EXCLUSIVE_LOCKS_REQUIRED ( ! cs ) LOCK_RETURNED ( cs ) { return cs ; }
inline Mutex & MaybeCheckNotHeld ( Mutex & cs ) EXCLUSIVE_LOCKS_REQUIRED ( ! cs ) LOCK_RETURNED ( cs ) { return cs ; }
inline Mutex * MaybeCheckNotHeld ( Mutex * cs ) EXCLUSIVE_LOCKS_REQUIRED ( ! cs ) LOCK_RETURNED ( cs ) { return cs ; }
inline Mutex * MaybeCheckNotHeld ( Mutex * cs ) EXCLUSIVE_LOCKS_REQUIRED ( ! cs ) LOCK_RETURNED ( cs ) { return cs ; }
// When locking a GlobalMutex, just check it is not locked in the surrounding scope
// When locking a GlobalMutex or RecursiveMutex, just check it is not
inline GlobalMutex & MaybeCheckNotHeld ( GlobalMutex & cs ) LOCKS_EXCLUDED ( cs ) LOCK_RETURNED ( cs ) { return cs ; }
// locked in the surrounding scope.
inline GlobalMutex * MaybeCheckNotHeld ( GlobalMutex * cs ) LOCKS_EXCLUDED ( cs ) LOCK_RETURNED ( cs ) { return cs ; }
template < typename MutexType >
inline MutexType & MaybeCheckNotHeld ( MutexType & m ) LOCKS_EXCLUDED ( m ) LOCK_RETURNED ( m ) { return m ; }
// When locking a RecursiveMutex, it's okay to already hold the lock
template < typename MutexType >
// but check that it is not known to be locked in the surrounding scope anyway
inline MutexType * MaybeCheckNotHeld ( MutexType * m ) LOCKS_EXCLUDED ( m ) LOCK_RETURNED ( m ) { return m ; }
inline RecursiveMutex & MaybeCheckNotHeld ( RecursiveMutex & cs ) LOCKS_EXCLUDED ( cs ) LOCK_RETURNED ( cs ) { return cs ; }
inline RecursiveMutex * MaybeCheckNotHeld ( RecursiveMutex * cs ) LOCKS_EXCLUDED ( cs ) LOCK_RETURNED ( cs ) { return cs ; }
# define LOCK(cs) DebugLock<decltype(cs)> UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
# define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
# define LOCK2(cs1, cs2) \
# define LOCK2(cs1, cs2) \
DebugLock< decltype ( cs1 ) > criticalblock1 ( MaybeCheckNotHeld ( cs1 ) , # cs1 , __FILE__ , __LINE__ ) ; \
UniqueLock criticalblock1 ( MaybeCheckNotHeld ( cs1 ) , # cs1 , __FILE__ , __LINE__ ) ; \
DebugLock< decltype ( cs2 ) > criticalblock2 ( MaybeCheckNotHeld ( cs2 ) , # cs2 , __FILE__ , __LINE__ )
UniqueLock criticalblock2 ( MaybeCheckNotHeld ( cs2 ) , # cs2 , __FILE__ , __LINE__ )
# define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true)
# define TRY_LOCK(cs, name) UniqueLock name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true)
# define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
# define WAIT_LOCK(cs, name) UniqueLock name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
# define ENTER_CRITICAL_SECTION(cs) \
# define ENTER_CRITICAL_SECTION(cs) \
{ \
{ \