Make the type of the read/write lock of AIThreadSafe a template parameter.
This allows passing a different type than the default AIRWLock for
debugging purposes.
The signature of the class used for RWLOCK should be:
struct RWLock {
// Default constructor.
RWLock(void);
// Block until it's safe to read the data.
// high_priority is a hint that granting this thread the read lock is more important than granting another thread a write lock.
void rdlock(bool high_priority = false);
// Release the obtained read lock.
void rdunlock();
// Block until it's safe to write to the data.
void wrlock();
// Release the obtained write lock.
void wrunlock();
// Convert the obtained write lock into a read lock.
void wr2rdlock();
// Block until it is possible to convert the obtained read lock into a write lock.
void rd2wrlock();
// Return true when a read or write is obtained and subsequent calls to release the lock are expected.
bool isLocked() const;
};
This commit is contained in:
@@ -106,9 +106,9 @@
|
|||||||
// on a compiler that doesn't need this hack.
|
// on a compiler that doesn't need this hack.
|
||||||
#define AI_NEED_ACCESS_CC (defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)) || (__GNUC__ < 4)))
|
#define AI_NEED_ACCESS_CC (defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ < 3)) || (__GNUC__ < 4)))
|
||||||
|
|
||||||
template<typename T> struct AIReadAccessConst;
|
template<typename T, typename RWLOCK> struct AIReadAccessConst;
|
||||||
template<typename T> struct AIReadAccess;
|
template<typename T, typename RWLOCK> struct AIReadAccess;
|
||||||
template<typename T> struct AIWriteAccess;
|
template<typename T, typename RWLOCK> struct AIWriteAccess;
|
||||||
template<typename T, typename MUTEX> struct AIAccessConst;
|
template<typename T, typename MUTEX> struct AIAccessConst;
|
||||||
template<typename T, typename MUTEX> struct AIAccess;
|
template<typename T, typename MUTEX> struct AIAccess;
|
||||||
template<typename T> struct AISTAccessConst;
|
template<typename T> struct AISTAccessConst;
|
||||||
@@ -225,17 +225,17 @@ protected:
|
|||||||
* </code>
|
* </code>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T, typename RWLOCK = AIRWLock>
|
||||||
class AIThreadSafe : public AIThreadSafeBits<T>
|
class AIThreadSafe : public AIThreadSafeBits<T>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
// Only these may access the object (through ptr()).
|
// Only these may access the object (through ptr()).
|
||||||
friend struct AIReadAccessConst<T>;
|
friend struct AIReadAccessConst<T, RWLOCK>;
|
||||||
friend struct AIReadAccess<T>;
|
friend struct AIReadAccess<T, RWLOCK>;
|
||||||
friend struct AIWriteAccess<T>;
|
friend struct AIWriteAccess<T, RWLOCK>;
|
||||||
|
|
||||||
// Locking control.
|
// Locking control.
|
||||||
AIRWLock mRWLock;
|
RWLOCK mRWLock;
|
||||||
|
|
||||||
// For use by AIThreadSafeDC
|
// For use by AIThreadSafeDC
|
||||||
AIThreadSafe(void) { }
|
AIThreadSafe(void) { }
|
||||||
@@ -310,20 +310,20 @@ public:
|
|||||||
*
|
*
|
||||||
* which is not possible with AITHREADSAFE.
|
* which is not possible with AITHREADSAFE.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T, typename RWLOCK = AIRWLock>
|
||||||
class AIThreadSafeDC : public AIThreadSafe<T>
|
class AIThreadSafeDC : public AIThreadSafe<T, RWLOCK>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Construct a wrapper around a default constructed object.
|
// Construct a wrapper around a default constructed object.
|
||||||
AIThreadSafeDC(void) { new (AIThreadSafe<T>::ptr()) T; }
|
AIThreadSafeDC(void) { new (AIThreadSafe<T, RWLOCK>::ptr()) T; }
|
||||||
// Allow an arbitrary parameter to be passed for construction.
|
// Allow an arbitrary parameter to be passed for construction.
|
||||||
template<typename T2> AIThreadSafeDC(T2 const& val) { new (AIThreadSafe<T>::ptr()) T(val); }
|
template<typename T2> AIThreadSafeDC(T2 const& val) { new (AIThreadSafe<T, RWLOCK>::ptr()) T(val); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read lock object and provide read access.
|
* @brief Read lock object and provide read access.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T, typename RWLOCK = AIRWLock>
|
||||||
struct AIReadAccessConst
|
struct AIReadAccessConst
|
||||||
{
|
{
|
||||||
//! Internal enum for the lock-type of the AI*Access object.
|
//! Internal enum for the lock-type of the AI*Access object.
|
||||||
@@ -336,8 +336,8 @@ struct AIReadAccessConst
|
|||||||
};
|
};
|
||||||
|
|
||||||
//! Construct a AIReadAccessConst from a constant AIThreadSafe.
|
//! Construct a AIReadAccessConst from a constant AIThreadSafe.
|
||||||
AIReadAccessConst(AIThreadSafe<T> const& wrapper, bool high_priority = false)
|
AIReadAccessConst(AIThreadSafe<T, RWLOCK> const& wrapper, bool high_priority = false)
|
||||||
: mWrapper(const_cast<AIThreadSafe<T>&>(wrapper)),
|
: mWrapper(const_cast<AIThreadSafe<T, RWLOCK>&>(wrapper)),
|
||||||
mState(readlocked)
|
mState(readlocked)
|
||||||
#if AI_NEED_ACCESS_CC
|
#if AI_NEED_ACCESS_CC
|
||||||
, mIsCopyConstructed(false)
|
, mIsCopyConstructed(false)
|
||||||
@@ -369,14 +369,14 @@ struct AIReadAccessConst
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Constructor used by AIReadAccess.
|
//! Constructor used by AIReadAccess.
|
||||||
AIReadAccessConst(AIThreadSafe<T>& wrapper, state_type state)
|
AIReadAccessConst(AIThreadSafe<T, RWLOCK>& wrapper, state_type state)
|
||||||
: mWrapper(wrapper), mState(state)
|
: mWrapper(wrapper), mState(state)
|
||||||
#if AI_NEED_ACCESS_CC
|
#if AI_NEED_ACCESS_CC
|
||||||
, mIsCopyConstructed(false)
|
, mIsCopyConstructed(false)
|
||||||
#endif
|
#endif
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
AIThreadSafe<T>& mWrapper; //!< Reference to the object that we provide access to.
|
AIThreadSafe<T, RWLOCK>& mWrapper; //!< Reference to the object that we provide access to.
|
||||||
state_type const mState; //!< The lock state that mWrapper is in.
|
state_type const mState; //!< The lock state that mWrapper is in.
|
||||||
|
|
||||||
#if AI_NEED_ACCESS_CC
|
#if AI_NEED_ACCESS_CC
|
||||||
@@ -393,39 +393,39 @@ private:
|
|||||||
/**
|
/**
|
||||||
* @brief Read lock object and provide read access, with possible promotion to write access.
|
* @brief Read lock object and provide read access, with possible promotion to write access.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T, typename RWLOCK = AIRWLock>
|
||||||
struct AIReadAccess : public AIReadAccessConst<T>
|
struct AIReadAccess : public AIReadAccessConst<T, RWLOCK>
|
||||||
{
|
{
|
||||||
typedef typename AIReadAccessConst<T>::state_type state_type;
|
typedef typename AIReadAccessConst<T, RWLOCK>::state_type state_type;
|
||||||
using AIReadAccessConst<T>::readlocked;
|
using AIReadAccessConst<T, RWLOCK>::readlocked;
|
||||||
|
|
||||||
//! Construct a AIReadAccess from a non-constant AIThreadSafe.
|
//! Construct a AIReadAccess from a non-constant AIThreadSafe.
|
||||||
AIReadAccess(AIThreadSafe<T>& wrapper, bool high_priority = false) : AIReadAccessConst<T>(wrapper, readlocked) { this->mWrapper.mRWLock.rdlock(high_priority); }
|
AIReadAccess(AIThreadSafe<T, RWLOCK>& wrapper, bool high_priority = false) : AIReadAccessConst<T, RWLOCK>(wrapper, readlocked) { this->mWrapper.mRWLock.rdlock(high_priority); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Constructor used by AIWriteAccess.
|
//! Constructor used by AIWriteAccess.
|
||||||
AIReadAccess(AIThreadSafe<T>& wrapper, state_type state) : AIReadAccessConst<T>(wrapper, state) { }
|
AIReadAccess(AIThreadSafe<T, RWLOCK>& wrapper, state_type state) : AIReadAccessConst<T, RWLOCK>(wrapper, state) { }
|
||||||
|
|
||||||
friend struct AIWriteAccess<T>;
|
friend struct AIWriteAccess<T, RWLOCK>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Write lock object and provide read/write access.
|
* @brief Write lock object and provide read/write access.
|
||||||
*/
|
*/
|
||||||
template<typename T>
|
template<typename T, typename RWLOCK = AIRWLock>
|
||||||
struct AIWriteAccess : public AIReadAccess<T>
|
struct AIWriteAccess : public AIReadAccess<T, RWLOCK>
|
||||||
{
|
{
|
||||||
using AIReadAccessConst<T>::readlocked;
|
using AIReadAccessConst<T, RWLOCK>::readlocked;
|
||||||
using AIReadAccessConst<T>::read2writelocked;
|
using AIReadAccessConst<T, RWLOCK>::read2writelocked;
|
||||||
using AIReadAccessConst<T>::writelocked;
|
using AIReadAccessConst<T, RWLOCK>::writelocked;
|
||||||
using AIReadAccessConst<T>::write2writelocked;
|
using AIReadAccessConst<T, RWLOCK>::write2writelocked;
|
||||||
|
|
||||||
//! Construct a AIWriteAccess from a non-constant AIThreadSafe.
|
//! Construct a AIWriteAccess from a non-constant AIThreadSafe.
|
||||||
AIWriteAccess(AIThreadSafe<T>& wrapper) : AIReadAccess<T>(wrapper, writelocked) { this->mWrapper.mRWLock.wrlock();}
|
AIWriteAccess(AIThreadSafe<T, RWLOCK>& wrapper) : AIReadAccess<T, RWLOCK>(wrapper, writelocked) { this->mWrapper.mRWLock.wrlock();}
|
||||||
|
|
||||||
//! Promote read access to write access.
|
//! Promote read access to write access.
|
||||||
explicit AIWriteAccess(AIReadAccess<T>& access)
|
explicit AIWriteAccess(AIReadAccess<T, RWLOCK>& access)
|
||||||
: AIReadAccess<T>(access.mWrapper, (access.mState == readlocked) ? read2writelocked : write2writelocked)
|
: AIReadAccess<T, RWLOCK>(access.mWrapper, (access.mState == readlocked) ? read2writelocked : write2writelocked)
|
||||||
{
|
{
|
||||||
if (this->mState == read2writelocked)
|
if (this->mState == read2writelocked)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user