diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index eff95d83f..425741601 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -2,7 +2,7 @@ * @file aithreadsafe.h * @brief Implementation of AIThreadSafe, AIReadAccessConst, AIReadAccess and AIWriteAccess. * - * Copyright (c) 2010, Aleric Inglewood. + * Copyright (c) 2010 - 2013, Aleric Inglewood. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,6 +31,9 @@ * Added AIThreadSafeSingleThread and friends. * Added AIAccessConst (and derived AIAccess from it) to allow read * access to a const AIThreadSafeSimple. + * + * 26/01/2013 + * Added support for LLCondition to AIThreadSafeSimple. */ // This file defines wrapper template classes for arbitrary types T @@ -106,8 +109,8 @@ template struct AIReadAccessConst; template struct AIReadAccess; template struct AIWriteAccess; -template struct AIAccessConst; -template struct AIAccess; +template struct AIAccessConst; +template struct AIAccess; template struct AISTAccessConst; template struct AISTAccess; @@ -456,16 +459,16 @@ struct AIWriteAccess : public AIReadAccess * * See also AIThreadSafe */ -template +template class AIThreadSafeSimple : public AIThreadSafeBits { protected: // Only this one may access the object (through ptr()). - friend struct AIAccessConst; - friend struct AIAccess; + friend struct AIAccessConst; + friend struct AIAccess; // Locking control. - LLMutex mMutex; + MUTEX mMutex; friend struct AIRegisteredStateMachinesList; // For use by AIThreadSafeSimpleDC and AIRegisteredStateMachinesList. @@ -476,6 +479,9 @@ public: // Only for use by AITHREADSAFESIMPLE, see below. AIThreadSafeSimple(T* object) { llassert(object == AIThreadSafeBits::ptr()); } + // If MUTEX is a LLCondition then this can be used to wake up the waiting thread. + void signal() { mMutex.signal(); } + #if LL_DEBUG // Can only be locked when there still exists an AIAccess object that // references this object and will access it upon destruction. @@ -506,6 +512,7 @@ public: * If that is needed, have a look at AIThreadSafeSimpleDC. */ #define AITHREADSAFESIMPLE(type, var, paramlist) AIThreadSafeSimple var(new (var.memory()) type paramlist) +#define AITHREADSAFESIMPLECONDITION(type, var, paramlist) AIThreadSafeSimple var(new (var.memory()) type paramlist) /** * @brief A wrapper class for objects that need to be accessed by more than one thread. @@ -536,18 +543,18 @@ public: * * which is not possible with AITHREADSAFESIMPLE. */ -template -class AIThreadSafeSimpleDC : public AIThreadSafeSimple +template +class AIThreadSafeSimpleDC : public AIThreadSafeSimple { public: // Construct a wrapper around a default constructed object. - AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple::ptr()) T; } + AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple::ptr()) T; } // Allow an arbitrary parameter to be passed for construction. - template AIThreadSafeSimpleDC(T2 const& val) { new (AIThreadSafeSimple::ptr()) T(val); } + template AIThreadSafeSimpleDC(T2 const& val) { new (AIThreadSafeSimple::ptr()) T(val); } protected: // For use by AIThreadSafeSimpleDCRootPool - AIThreadSafeSimpleDC(LLAPRRootPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } + AIThreadSafeSimpleDC(LLAPRRootPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } }; // Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of @@ -587,11 +594,11 @@ public: /** * @brief Write lock object and provide read access. */ -template +template struct AIAccessConst { //! Construct a AIAccessConst from a constant AIThreadSafeSimple. - AIAccessConst(AIThreadSafeSimple const& wrapper) : mWrapper(const_cast&>(wrapper)) + AIAccessConst(AIThreadSafeSimple const& wrapper) : mWrapper(const_cast&>(wrapper)) #if AI_NEED_ACCESS_CC , mIsCopyConstructed(false) #endif @@ -613,8 +620,11 @@ struct AIAccessConst this->mWrapper.mMutex.unlock(); } + // If MUTEX is an LLCondition, then this can be used to wait for a signal. + void wait() { this->mWrapper.mMutex.wait(); } + protected: - AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. + AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. #if AI_NEED_ACCESS_CC bool mIsCopyConstructed; @@ -630,11 +640,11 @@ private: /** * @brief Write lock object and provide read/write access. */ -template -struct AIAccess : public AIAccessConst +template +struct AIAccess : public AIAccessConst { //! Construct a AIAccess from a non-constant AIThreadSafeSimple. - AIAccess(AIThreadSafeSimple& wrapper) : AIAccessConst(wrapper) { } + AIAccess(AIThreadSafeSimple& wrapper) : AIAccessConst(wrapper) { } //! Access the underlaying object for (read and) write access. T* operator->() const { return this->mWrapper.ptr(); }