You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
7.5 KiB

/*
* 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.
*/
// <COMPONENT>: util
// <FILE-TYPE>: 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 LOCK> class /*<UTILITY>*/ 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 LOCK> class /*<UTILITY>*/ 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 LOCK, NATIVE_TID (*GetTidFn)()> class /*<UTILITY>*/ 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<LOCK, GetTidFn>::READ: _lock->ReadLock(_tid); break;
case RWLOCKER_WITH_TID<LOCK, GetTidFn>::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 <typename CSTYPE> class /*<UTILITY>*/ 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