/* * Copyright 2002-2019 Intel Corporation. * * This software and the related documents are Intel copyrighted materials, and your * use of them is governed by the express license under which they were provided to * you ("License"). Unless the License provides otherwise, you may not use, modify, * copy, publish, distribute, disclose or transmit this software or the related * documents without Intel's prior written permission. * * This software and the related documents are provided as is, with no express or * implied warranties, other than those that are expressly stated in the License. */ // : util // : component public header #ifndef UTIL_LOCKER_HPP #define UTIL_LOCKER_HPP namespace UTIL { /*! * A simple utility that manages a mutex lock. The lock is automatically acquired on * entry to the scope and released on exit. * * @param LOCK Any type that supports Lock() and Unlock() methods with the usual semantics. */ template class /**/ LOCKER { public: /*! * @param[in] lock The lock to acquire. * @param[in] acquire If TRUE, the constructor acquires the lock. */ LOCKER(LOCK *lock, bool acquire = true) : _lock(lock), _isLocked(acquire) { if (acquire) _lock->Lock(); } /*! * The destructor releases the lock unless it was manually released via Unlock(). */ ~LOCKER() { if (_isLocked) _lock->Unlock(); } /*! * Manually release the lock. */ void Unlock() { _lock->Unlock(); _isLocked = false; } /*! * Manually acquire the lock. This only makes sense if the lock was manually released * via Unlock(). No error checking is done to prevent self-deadlock. */ void Lock() { _lock->Lock(); _isLocked = true; } /*! * Indicate that the lock has been acquired or released outside of this wrapper. * * @param[in] isLocked TRUE if the lock has been acquired. */ void SetLocked(bool isLocked) { _isLocked = isLocked; } private: LOCK *_lock; // _lock might be dead/deallocated while we are inside a scope, we don't want to unlock it in this case (will cause exception). // _isLocked gives us a way out in such a case (See SetLocked()). bool _isLocked; }; /*! * A simple utility that manages a RW mutex lock for READ lock oprtations. The lock is automatically acquired on * entry to the scope and released on exit. * * @param LOCK Any type that supports ReadLock(), WriteLock() and Unlock() methods with the usual semantics. */ template class /**/ RWLOCKER { public: enum LockType { READ, WRITE }; /*! * @param[in] lock The lock to acquire. * @param[in] acquire If TRUE, the constructor acquires the lock. */ RWLOCKER(LOCK *lock, LockType lock_type, bool acquire = true) : _lock(lock), _isLocked(false) { if (acquire) { Lock(lock_type); } } /*! * The destructor releases the lock unless it was manually released via Unlock(). */ ~RWLOCKER() { Unlock(); } /*! * Manually release the lock. */ void Unlock() { if (_isLocked) { if (NULL != _lock) { _lock->Unlock(); } _isLocked = false; } } /*! * Manually acquire the lock. This only makes sense if the lock was manually released * via Unlock(). No error checking is done to prevent self-deadlock. */ void Lock(LockType lock_type) { if (NULL != _lock) { switch (lock_type) { case RWLOCKER::READ: _lock->ReadLock(); break; case RWLOCKER::WRITE: _lock->WriteLock(); break; } } _isLocked = true; } private: LOCK *_lock; bool _isLocked; }; #ifdef CC_FAST_LOOKUP /*! * A simple utility that manages a RW mutex lock for READ lock oprtations. The lock is automatically acquired on * entry to the scope and released on exit. * * @param LOCK Any type that supports ReadLock(), WriteLock() and Unlock() methods with the usual semantics. */ template class /**/ RWLOCKER_WITH_TID { public: enum LockType { READ, WRITE }; /*! * @param[in] lock The lock to acquire. * @param[in] acquire If TRUE, the constructor acquires the lock. */ RWLOCKER_WITH_TID(LOCK *lock, LockType lock_type, bool acquire = true) : _lock(lock), _tid(INVALID_NATIVE_TID) { if (acquire) { Lock(lock_type); } } /*! * The destructor releases the lock unless it was manually released via Unlock(). */ ~RWLOCKER_WITH_TID() { Unlock(); } /*! * Manually release the lock. */ void Unlock() { if (_tid != INVALID_NATIVE_TID && NULL != _lock) { _lock->Unlock(_tid); _tid = INVALID_NATIVE_TID; } } /*! * Manually acquire the lock. This only makes sense if the lock was manually released * via Unlock(). No error checking is done to prevent self-deadlock. */ void Lock(LockType lock_type) { if (_lock == NULL) return; _tid = GetTidFn(); switch (lock_type) { case RWLOCKER_WITH_TID::READ: _lock->ReadLock(_tid); break; case RWLOCKER_WITH_TID::WRITE: _lock->WriteLock(_tid); break; } } private: LOCK *_lock; NATIVE_TID _tid; }; #endif /*! * A simple utility that manages a Microsoft CRITICAL_SECTION. The critical section * is automatically acquired on entry to the scope and released on exit. * * @param CSTYPE Usually this is the Microsoft CRITICAL_SECTION type, but you can * use any type that works with functions named EnterCriticalSection() * and LeaveCriticalSection(). */ template class /**/ SCOPED_CRITICAL_SECTION { public: /*! * @param[in] cs The critical section to acquire. * @param[in] acquire If TRUE, the constructor acquires the critical section. */ SCOPED_CRITICAL_SECTION(CSTYPE *cs, bool acquire = true) : _cs(cs), _isLocked(acquire) { if (acquire) EnterCriticalSection(cs); } /*! * The destructor releases the critical section unless it was manually released via Unlock(). */ ~SCOPED_CRITICAL_SECTION() { if (_isLocked) LeaveCriticalSection(_cs); } /*! * Manually release the critical section. */ void Unlock() { LeaveCriticalSection(_cs); _isLocked = false; } /*! * Manually acquire the critical section. This only makes sense if the critical section * was manually released via Unlock(). No error checking is done to prevent self-deadlock. */ void Lock() { EnterCriticalSection(_cs); _isLocked = true; } /*! * Indicate that the critical section has been acquired or released outside of this wrapper. * * @param[in] isLocked TRUE if the critical section has been acquired. */ void SetLocked(bool isLocked) { _isLocked = isLocked; } private: CSTYPE *_cs; bool _isLocked; }; } // namespace #endif // file guard