SL-10291 Replace apr_mutex with standard C++11 functionality
parent
127ed9c678
commit
26fae750ba
|
|
@ -1070,6 +1070,7 @@ Nicky Dasmijn
|
|||
STORM-2010
|
||||
STORM-2082
|
||||
MAINT-6665
|
||||
SL-10291
|
||||
SL-10293
|
||||
Nicky Perian
|
||||
OPEN-1
|
||||
|
|
|
|||
|
|
@ -28,13 +28,12 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
#include "llapr.h"
|
||||
#include "llmutex.h"
|
||||
#include "apr_dso.h"
|
||||
#include "llthreadlocalstorage.h"
|
||||
|
||||
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
|
||||
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
|
||||
apr_thread_mutex_t *gLogMutexp = NULL;
|
||||
apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
|
||||
|
||||
const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
|
||||
|
||||
|
|
@ -48,10 +47,6 @@ void ll_init_apr()
|
|||
if (!gAPRPoolp)
|
||||
{
|
||||
apr_pool_create(&gAPRPoolp, NULL);
|
||||
|
||||
// Initialize the logging mutex
|
||||
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
}
|
||||
|
||||
if(!LLAPRFile::sAPRFilePoolp)
|
||||
|
|
@ -75,23 +70,6 @@ void ll_cleanup_apr()
|
|||
|
||||
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
|
||||
|
||||
if (gLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gLogMutexp);
|
||||
gLogMutexp = NULL;
|
||||
}
|
||||
if (gCallStacksLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gCallStacksLogMutexp);
|
||||
gCallStacksLogMutexp = NULL;
|
||||
}
|
||||
|
||||
LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
|
||||
|
||||
if (gAPRPoolp)
|
||||
|
|
@ -168,26 +146,19 @@ apr_pool_t* LLAPRPool::getAPRPool()
|
|||
LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
|
||||
: LLAPRPool(parent, size, releasePoolFlag),
|
||||
mNumActiveRef(0),
|
||||
mNumTotalRef(0),
|
||||
mMutexPool(NULL),
|
||||
mMutexp(NULL)
|
||||
mNumTotalRef(0)
|
||||
{
|
||||
//create mutex
|
||||
if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
|
||||
{
|
||||
apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
|
||||
apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
|
||||
mMutexp.reset(new std::mutex());
|
||||
}
|
||||
}
|
||||
|
||||
LLVolatileAPRPool::~LLVolatileAPRPool()
|
||||
{
|
||||
//delete mutex
|
||||
if(mMutexp)
|
||||
{
|
||||
apr_thread_mutex_destroy(mMutexp);
|
||||
apr_pool_destroy(mMutexPool);
|
||||
}
|
||||
mMutexp.reset();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -201,7 +172,7 @@ apr_pool_t* LLVolatileAPRPool::getAPRPool()
|
|||
|
||||
apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
|
||||
{
|
||||
LLScopedLock lock(mMutexp) ;
|
||||
LLScopedLock lock(mMutexp.get()) ;
|
||||
|
||||
mNumTotalRef++ ;
|
||||
mNumActiveRef++ ;
|
||||
|
|
@ -216,7 +187,7 @@ apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
|
|||
|
||||
void LLVolatileAPRPool::clearVolatileAPRPool()
|
||||
{
|
||||
LLScopedLock lock(mMutexp) ;
|
||||
LLScopedLock lock(mMutexp.get());
|
||||
|
||||
if(mNumActiveRef > 0)
|
||||
{
|
||||
|
|
@ -250,44 +221,6 @@ BOOL LLVolatileAPRPool::isFull()
|
|||
{
|
||||
return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
|
||||
}
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// LLScopedLock
|
||||
//
|
||||
LLScopedLock::LLScopedLock(apr_thread_mutex_t* mutex) : mMutex(mutex)
|
||||
{
|
||||
if(mutex)
|
||||
{
|
||||
if(ll_apr_warn_status(apr_thread_mutex_lock(mMutex)))
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLocked = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
LLScopedLock::~LLScopedLock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
void LLScopedLock::unlock()
|
||||
{
|
||||
if(mLocked)
|
||||
{
|
||||
if(!ll_apr_warn_status(apr_thread_mutex_unlock(mMutex)))
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -36,15 +36,23 @@
|
|||
#include <boost/noncopyable.hpp>
|
||||
#include "llwin32headerslean.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include "apr_thread_mutex.h"
|
||||
#include "apr_getopt.h"
|
||||
#include "apr_signal.h"
|
||||
#include "apr_atomic.h"
|
||||
|
||||
#include "llstring.h"
|
||||
|
||||
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
|
||||
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4265)
|
||||
#endif
|
||||
// warning C4265: 'std::_Pad' : class has virtual functions, but destructor is not virtual
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
struct apr_dso_handle_t;
|
||||
/**
|
||||
|
|
@ -120,50 +128,9 @@ private:
|
|||
S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
|
||||
S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
|
||||
|
||||
apr_thread_mutex_t *mMutexp;
|
||||
apr_pool_t *mMutexPool;
|
||||
std::unique_ptr<std::mutex> mMutexp;
|
||||
} ;
|
||||
|
||||
/**
|
||||
* @class LLScopedLock
|
||||
* @brief Small class to help lock and unlock mutexes.
|
||||
*
|
||||
* This class is used to have a stack level lock once you already have
|
||||
* an apr mutex handy. The constructor handles the lock, and the
|
||||
* destructor handles the unlock. Instances of this class are
|
||||
* <b>not</b> thread safe.
|
||||
*/
|
||||
class LL_COMMON_API LLScopedLock : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor which accepts a mutex, and locks it.
|
||||
*
|
||||
* @param mutex An allocated APR mutex. If you pass in NULL,
|
||||
* this wrapper will not lock.
|
||||
*/
|
||||
LLScopedLock(apr_thread_mutex_t* mutex);
|
||||
|
||||
/**
|
||||
* @brief Destructor which unlocks the mutex if still locked.
|
||||
*/
|
||||
~LLScopedLock();
|
||||
|
||||
/**
|
||||
* @brief Check lock.
|
||||
*/
|
||||
bool isLocked() const { return mLocked; }
|
||||
|
||||
/**
|
||||
* @brief This method unlocks the mutex.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
protected:
|
||||
bool mLocked;
|
||||
apr_thread_mutex_t* mMutex;
|
||||
};
|
||||
|
||||
template <typename Type> class LLAtomic32
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -1096,6 +1096,9 @@ namespace
|
|||
}
|
||||
|
||||
namespace {
|
||||
LLMutex gLogMutex;
|
||||
LLMutex gCallStacksLogMutex;
|
||||
|
||||
bool checkLevelMap(const LevelMap& map, const std::string& key,
|
||||
LLError::ELevel& level)
|
||||
{
|
||||
|
|
@ -1135,56 +1138,6 @@ namespace {
|
|||
}
|
||||
return found_level;
|
||||
}
|
||||
|
||||
class LogLock
|
||||
{
|
||||
public:
|
||||
LogLock();
|
||||
~LogLock();
|
||||
bool ok() const { return mOK; }
|
||||
private:
|
||||
bool mLocked;
|
||||
bool mOK;
|
||||
};
|
||||
|
||||
LogLock::LogLock()
|
||||
: mLocked(false), mOK(false)
|
||||
{
|
||||
if (!gLogMutexp)
|
||||
{
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int MAX_RETRIES = 5;
|
||||
for (int attempts = 0; attempts < MAX_RETRIES; ++attempts)
|
||||
{
|
||||
apr_status_t s = apr_thread_mutex_trylock(gLogMutexp);
|
||||
if (!APR_STATUS_IS_EBUSY(s))
|
||||
{
|
||||
mLocked = true;
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ms_sleep(1);
|
||||
//apr_thread_yield();
|
||||
// Just yielding won't necessarily work, I had problems with
|
||||
// this on Linux - doug 12/02/04
|
||||
}
|
||||
|
||||
// We're hosed, we can't get the mutex. Blah.
|
||||
std::cerr << "LogLock::LogLock: failed to get mutex for log"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
LogLock::~LogLock()
|
||||
{
|
||||
if (mLocked)
|
||||
{
|
||||
apr_thread_mutex_unlock(gLogMutexp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace LLError
|
||||
|
|
@ -1192,8 +1145,8 @@ namespace LLError
|
|||
|
||||
bool Log::shouldLog(CallSite& site)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1243,11 +1196,11 @@ namespace LLError
|
|||
|
||||
std::ostringstream* Log::out()
|
||||
{
|
||||
LogLock lock;
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
// If we hit a logging request very late during shutdown processing,
|
||||
// when either of the relevant LLSingletons has already been deleted,
|
||||
// DO NOT resurrect them.
|
||||
if (lock.ok() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
|
||||
if (lock.isLocked() && ! (Settings::wasDeleted() || Globals::wasDeleted()))
|
||||
{
|
||||
Globals* g = Globals::getInstance();
|
||||
|
||||
|
|
@ -1263,8 +1216,8 @@ namespace LLError
|
|||
|
||||
void Log::flush(std::ostringstream* out, char* message)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1303,8 +1256,8 @@ namespace LLError
|
|||
|
||||
void Log::flush(std::ostringstream* out, const CallSite& site)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex,5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1469,69 +1422,6 @@ namespace LLError
|
|||
char** LLCallStacks::sBuffer = NULL ;
|
||||
S32 LLCallStacks::sIndex = 0 ;
|
||||
|
||||
#define SINGLE_THREADED 1
|
||||
|
||||
class CallStacksLogLock
|
||||
{
|
||||
public:
|
||||
CallStacksLogLock();
|
||||
~CallStacksLogLock();
|
||||
|
||||
#if SINGLE_THREADED
|
||||
bool ok() const { return true; }
|
||||
#else
|
||||
bool ok() const { return mOK; }
|
||||
private:
|
||||
bool mLocked;
|
||||
bool mOK;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if SINGLE_THREADED
|
||||
CallStacksLogLock::CallStacksLogLock()
|
||||
{
|
||||
}
|
||||
CallStacksLogLock::~CallStacksLogLock()
|
||||
{
|
||||
}
|
||||
#else
|
||||
CallStacksLogLock::CallStacksLogLock()
|
||||
: mLocked(false), mOK(false)
|
||||
{
|
||||
if (!gCallStacksLogMutexp)
|
||||
{
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int MAX_RETRIES = 5;
|
||||
for (int attempts = 0; attempts < MAX_RETRIES; ++attempts)
|
||||
{
|
||||
apr_status_t s = apr_thread_mutex_trylock(gCallStacksLogMutexp);
|
||||
if (!APR_STATUS_IS_EBUSY(s))
|
||||
{
|
||||
mLocked = true;
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ms_sleep(1);
|
||||
}
|
||||
|
||||
// We're hosed, we can't get the mutex. Blah.
|
||||
std::cerr << "CallStacksLogLock::CallStacksLogLock: failed to get mutex for log"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
CallStacksLogLock::~CallStacksLogLock()
|
||||
{
|
||||
if (mLocked)
|
||||
{
|
||||
apr_thread_mutex_unlock(gCallStacksLogMutexp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//static
|
||||
void LLCallStacks::allocateStackBuffer()
|
||||
{
|
||||
|
|
@ -1560,8 +1450,8 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::push(const char* function, const int line)
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gCallStacksLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1595,8 +1485,8 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::end(std::ostringstream* _out)
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gCallStacksLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1617,8 +1507,8 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::print()
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gCallStacksLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -1655,8 +1545,8 @@ namespace LLError
|
|||
|
||||
bool debugLoggingEnabled(const std::string& tag)
|
||||
{
|
||||
LogLock lock;
|
||||
if (!lock.ok())
|
||||
LLMutexTrylock lock(&gLogMutex, 5);
|
||||
if (!lock.isLocked())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines),
|
||||
mMutex(NULL)
|
||||
mMutex()
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,41 +30,19 @@
|
|||
|
||||
#include "llmutex.h"
|
||||
#include "llthread.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
//============================================================================
|
||||
|
||||
LLMutex::LLMutex(apr_pool_t *poolp) :
|
||||
mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
|
||||
LLMutex::LLMutex() :
|
||||
mCount(0),
|
||||
mLockingThread(NO_THREAD)
|
||||
{
|
||||
//if (poolp)
|
||||
//{
|
||||
// mIsLocalPool = FALSE;
|
||||
// mAPRPoolp = poolp;
|
||||
//}
|
||||
//else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
|
||||
}
|
||||
|
||||
|
||||
LLMutex::~LLMutex()
|
||||
{
|
||||
#if MUTEX_DEBUG
|
||||
//bad assertion, the subclass LLSignal might be "locked", and that's OK
|
||||
//llassert_always(!isLocked()); // better not be locked!
|
||||
#endif
|
||||
if (ll_apr_is_initialized())
|
||||
{
|
||||
apr_thread_mutex_destroy(mAPRMutexp);
|
||||
if (mIsLocalPool)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
}
|
||||
}
|
||||
mAPRMutexp = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -76,7 +54,7 @@ void LLMutex::lock()
|
|||
return;
|
||||
}
|
||||
|
||||
apr_thread_mutex_lock(mAPRMutexp);
|
||||
mMutex.lock();
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
// Have to have the lock before we can access the debug info
|
||||
|
|
@ -106,19 +84,18 @@ void LLMutex::unlock()
|
|||
#endif
|
||||
|
||||
mLockingThread = NO_THREAD;
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
mMutex.unlock();
|
||||
}
|
||||
|
||||
bool LLMutex::isLocked()
|
||||
{
|
||||
apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
|
||||
if (APR_STATUS_IS_EBUSY(status))
|
||||
if (!mMutex.try_lock())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
apr_thread_mutex_unlock(mAPRMutexp);
|
||||
mMutex.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -141,8 +118,7 @@ bool LLMutex::trylock()
|
|||
return true;
|
||||
}
|
||||
|
||||
apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp));
|
||||
if (APR_STATUS_IS_EBUSY(status))
|
||||
if (!mMutex.try_lock())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -161,45 +137,95 @@ bool LLMutex::trylock()
|
|||
|
||||
//============================================================================
|
||||
|
||||
LLCondition::LLCondition(apr_pool_t *poolp) :
|
||||
LLMutex(poolp)
|
||||
LLCondition::LLCondition() :
|
||||
LLMutex()
|
||||
{
|
||||
// base class (LLMutex) has already ensured that mAPRPoolp is set up.
|
||||
|
||||
apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
|
||||
}
|
||||
|
||||
|
||||
LLCondition::~LLCondition()
|
||||
{
|
||||
apr_thread_cond_destroy(mAPRCondp);
|
||||
mAPRCondp = NULL;
|
||||
}
|
||||
|
||||
|
||||
void LLCondition::wait()
|
||||
{
|
||||
if (!isLocked())
|
||||
{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
|
||||
apr_thread_mutex_lock(mAPRMutexp);
|
||||
#if MUTEX_DEBUG
|
||||
// avoid asserts on destruction in non-release builds
|
||||
U32 id = LLThread::currentID();
|
||||
mIsLocked[id] = TRUE;
|
||||
#endif
|
||||
}
|
||||
apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
|
||||
std::unique_lock< std::mutex > lock(mMutex);
|
||||
mCond.wait(lock);
|
||||
}
|
||||
|
||||
void LLCondition::signal()
|
||||
{
|
||||
apr_thread_cond_signal(mAPRCondp);
|
||||
mCond.notify_one();
|
||||
}
|
||||
|
||||
void LLCondition::broadcast()
|
||||
{
|
||||
apr_thread_cond_broadcast(mAPRCondp);
|
||||
mCond.notify_all();
|
||||
}
|
||||
|
||||
|
||||
|
||||
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex)
|
||||
: mMutex(mutex),
|
||||
mLocked(false)
|
||||
{
|
||||
if (mMutex)
|
||||
mLocked = mMutex->trylock();
|
||||
}
|
||||
|
||||
LLMutexTrylock::LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms)
|
||||
: mMutex(mutex),
|
||||
mLocked(false)
|
||||
{
|
||||
if (!mMutex)
|
||||
return;
|
||||
|
||||
for (U32 i = 0; i < aTries; ++i)
|
||||
{
|
||||
mLocked = mMutex->trylock();
|
||||
if (mLocked)
|
||||
break;
|
||||
ms_sleep(delay_ms);
|
||||
}
|
||||
}
|
||||
|
||||
LLMutexTrylock::~LLMutexTrylock()
|
||||
{
|
||||
if (mMutex && mLocked)
|
||||
mMutex->unlock();
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
// LLScopedLock
|
||||
//
|
||||
LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex)
|
||||
{
|
||||
if(mutex)
|
||||
{
|
||||
mutex->lock();
|
||||
mLocked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
LLScopedLock::~LLScopedLock()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
void LLScopedLock::unlock()
|
||||
{
|
||||
if(mLocked)
|
||||
{
|
||||
mMutex->unlock();
|
||||
mLocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -28,6 +28,19 @@
|
|||
#define LL_LLMUTEX_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable:4265)
|
||||
#endif
|
||||
// 'std::_Pad' : class has virtual functions, but destructor is not virtual
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
@ -37,10 +50,6 @@
|
|||
#include <map>
|
||||
#endif
|
||||
|
||||
struct apr_thread_mutex_t;
|
||||
struct apr_pool_t;
|
||||
struct apr_thread_cond_t;
|
||||
|
||||
class LL_COMMON_API LLMutex
|
||||
{
|
||||
public:
|
||||
|
|
@ -49,7 +58,7 @@ public:
|
|||
NO_THREAD = 0xFFFFFFFF
|
||||
} e_locking_thread;
|
||||
|
||||
LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex
|
||||
LLMutex();
|
||||
virtual ~LLMutex();
|
||||
|
||||
void lock(); // blocks
|
||||
|
|
@ -60,13 +69,10 @@ public:
|
|||
U32 lockingThread() const; //get ID of locking thread
|
||||
|
||||
protected:
|
||||
apr_thread_mutex_t *mAPRMutexp;
|
||||
std::mutex mMutex;
|
||||
mutable U32 mCount;
|
||||
mutable U32 mLockingThread;
|
||||
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
|
||||
#if MUTEX_DEBUG
|
||||
std::map<U32, BOOL> mIsLocked;
|
||||
#endif
|
||||
|
|
@ -76,7 +82,7 @@ protected:
|
|||
class LL_COMMON_API LLCondition : public LLMutex
|
||||
{
|
||||
public:
|
||||
LLCondition(apr_pool_t* apr_poolp); // Defaults to global pool, could use the thread pool as well.
|
||||
LLCondition();
|
||||
~LLCondition();
|
||||
|
||||
void wait(); // blocks
|
||||
|
|
@ -84,7 +90,7 @@ public:
|
|||
void broadcast();
|
||||
|
||||
protected:
|
||||
apr_thread_cond_t* mAPRCondp;
|
||||
std::condition_variable mCond;
|
||||
};
|
||||
|
||||
class LLMutexLock
|
||||
|
|
@ -119,19 +125,9 @@ private:
|
|||
class LLMutexTrylock
|
||||
{
|
||||
public:
|
||||
LLMutexTrylock(LLMutex* mutex)
|
||||
: mMutex(mutex),
|
||||
mLocked(false)
|
||||
{
|
||||
if (mMutex)
|
||||
mLocked = mMutex->trylock();
|
||||
}
|
||||
|
||||
~LLMutexTrylock()
|
||||
{
|
||||
if (mMutex && mLocked)
|
||||
mMutex->unlock();
|
||||
}
|
||||
LLMutexTrylock(LLMutex* mutex);
|
||||
LLMutexTrylock(LLMutex* mutex, U32 aTries, U32 delay_ms = 10);
|
||||
~LLMutexTrylock();
|
||||
|
||||
bool isLocked() const
|
||||
{
|
||||
|
|
@ -142,4 +138,43 @@ private:
|
|||
LLMutex* mMutex;
|
||||
bool mLocked;
|
||||
};
|
||||
#endif // LL_LLTHREAD_H
|
||||
|
||||
/**
|
||||
* @class LLScopedLock
|
||||
* @brief Small class to help lock and unlock mutexes.
|
||||
*
|
||||
* The constructor handles the lock, and the destructor handles
|
||||
* the unlock. Instances of this class are <b>not</b> thread safe.
|
||||
*/
|
||||
class LL_COMMON_API LLScopedLock : private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor which accepts a mutex, and locks it.
|
||||
*
|
||||
* @param mutex An allocated mutex. If you pass in NULL,
|
||||
* this wrapper will not lock.
|
||||
*/
|
||||
LLScopedLock(std::mutex* mutex);
|
||||
|
||||
/**
|
||||
* @brief Destructor which unlocks the mutex if still locked.
|
||||
*/
|
||||
~LLScopedLock();
|
||||
|
||||
/**
|
||||
* @brief Check lock.
|
||||
*/
|
||||
bool isLocked() const { return mLocked; }
|
||||
|
||||
/**
|
||||
* @brief This method unlocks the mutex.
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
protected:
|
||||
bool mLocked;
|
||||
std::mutex* mMutex;
|
||||
};
|
||||
|
||||
#endif // LL_LLMUTEX_H
|
||||
|
|
|
|||
|
|
@ -186,8 +186,8 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
|
|||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mDataLock = new LLMutex(mAPRPoolp);
|
||||
mRunCondition = new LLCondition();
|
||||
mDataLock = new LLMutex();
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
|
||||
|
|
@ -413,7 +413,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
|
|||
{
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -738,7 +738,7 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp)
|
|||
getSystemTime(&time_last);
|
||||
uuids_this_tick = uuids_per_tick;
|
||||
init = TRUE;
|
||||
mMutex = new LLMutex(NULL);
|
||||
mMutex = new LLMutex();
|
||||
}
|
||||
|
||||
uuid_time_t time_now = {0,0};
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
|
||||
LLQueuedThread(name, threaded, should_pause)
|
||||
{
|
||||
mDeleteMutex = new LLMutex(NULL);
|
||||
mDeleteMutex = new LLMutex();
|
||||
|
||||
if(!mLocalAPRFilePoolp)
|
||||
{
|
||||
|
|
@ -204,7 +204,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
|
|||
mWorkerClassName(name),
|
||||
mRequestHandle(LLWorkerThread::nullHandle()),
|
||||
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
||||
mMutex(NULL),
|
||||
mMutex(),
|
||||
mWorkFlags(0)
|
||||
{
|
||||
if (!mWorkerThread)
|
||||
|
|
|
|||
|
|
@ -333,7 +333,7 @@ LLMutex *getCurlMutex()
|
|||
|
||||
if (!sHandleMutexp)
|
||||
{
|
||||
sHandleMutexp = new LLMutex(NULL);
|
||||
sHandleMutexp = new LLMutex();
|
||||
}
|
||||
|
||||
return sHandleMutexp;
|
||||
|
|
@ -389,7 +389,7 @@ void initialize()
|
|||
S32 mutex_count = CRYPTO_num_locks();
|
||||
for (S32 i = 0; i < mutex_count; i++)
|
||||
{
|
||||
sSSLMutex.push_back(LLMutex_ptr(new LLMutex(NULL)));
|
||||
sSSLMutex.push_back(LLMutex_ptr(new LLMutex()));
|
||||
}
|
||||
CRYPTO_set_id_callback(&ssl_thread_id);
|
||||
CRYPTO_set_locking_callback(&ssl_locking_callback);
|
||||
|
|
|
|||
|
|
@ -594,7 +594,7 @@ void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_
|
|||
{
|
||||
sUseNewByteRange = use_new_byte_range;
|
||||
sMinimalReverseByteRangePercent = minimal_reverse_byte_range_percent;
|
||||
sMutex = new LLMutex(NULL);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
|
||||
: LLQueuedThread("imagedecode", threaded)
|
||||
{
|
||||
mCreationMutex = new LLMutex(getAPRPool());
|
||||
mCreationMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//virtual
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ LLVolumeMgr::LLVolumeMgr()
|
|||
{
|
||||
// the LLMutex magic interferes with easy unit testing,
|
||||
// so you now must manually call useMutex() to use it
|
||||
//mDataMutex = new LLMutex(gAPRPoolp);
|
||||
//mDataMutex = new LLMutex();
|
||||
}
|
||||
|
||||
LLVolumeMgr::~LLVolumeMgr()
|
||||
|
|
@ -214,7 +214,7 @@ void LLVolumeMgr::useMutex()
|
|||
{
|
||||
if (!mDataMutex)
|
||||
{
|
||||
mDataMutex = new LLMutex(gAPRPoolp);
|
||||
mDataMutex = new LLMutex();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -265,7 +265,7 @@ void LLBufferArray::setThreaded(bool threaded)
|
|||
{
|
||||
if(!mMutexp)
|
||||
{
|
||||
mMutexp = new LLMutex(NULL);
|
||||
mMutexp = new LLMutex();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP
|
|||
|
||||
LLProxy::LLProxy():
|
||||
mHTTPProxyEnabled(false),
|
||||
mProxyMutex(NULL),
|
||||
mProxyMutex(),
|
||||
mUDPProxy(),
|
||||
mTCPProxy(),
|
||||
mHTTPProxy(),
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)
|
|||
}
|
||||
|
||||
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
|
||||
mInputMutex(gAPRPoolp),
|
||||
mOutputMutex(gAPRPoolp),
|
||||
mInputMutex(),
|
||||
mOutputMutex(),
|
||||
mOutputStartIndex(0),
|
||||
mOwner(owner),
|
||||
mSocket(socket)
|
||||
|
|
|
|||
|
|
@ -80,11 +80,11 @@ protected:
|
|||
};
|
||||
|
||||
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
|
||||
mIncomingQueueMutex(gAPRPoolp)
|
||||
mIncomingQueueMutex()
|
||||
{
|
||||
if(!sInstancesMutex)
|
||||
{
|
||||
sInstancesMutex = new LLMutex(gAPRPoolp);
|
||||
sInstancesMutex = new LLMutex();
|
||||
}
|
||||
|
||||
mOwner = owner;
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
|
|||
mDataFP(NULL),
|
||||
mIndexFP(NULL)
|
||||
{
|
||||
mDataMutex = new LLMutex(0);
|
||||
mDataMutex = new LLMutex();
|
||||
|
||||
S32 i;
|
||||
for (i = 0; i < VFSLOCK_COUNT; i++)
|
||||
|
|
|
|||
|
|
@ -2148,7 +2148,7 @@ bool LLAppViewer::initThreads()
|
|||
|
||||
if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog)
|
||||
{
|
||||
LLTrace::BlockTimer::setLogLock(new LLMutex(NULL));
|
||||
LLTrace::BlockTimer::setLogLock(new LLMutex());
|
||||
mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::BlockTimer::sLogName);
|
||||
mFastTimerLogThread->start();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -315,7 +315,7 @@ void LLDirPickerThread::run()
|
|||
//static
|
||||
void LLDirPickerThread::initClass()
|
||||
{
|
||||
sMutex = new LLMutex(NULL);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i
|
|||
mPageSize(gSavedSettings.getS32("ConversationHistoryPageSize")),
|
||||
mAccountName(session_id[LL_FCP_ACCOUNT_NAME]),
|
||||
mCompleteName(session_id[LL_FCP_COMPLETE_NAME]),
|
||||
mMutex(NULL),
|
||||
mMutex(),
|
||||
mShowHistory(false),
|
||||
mMessages(NULL),
|
||||
mHistoryThreadsBusy(false),
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ mCalculateBtn(NULL)
|
|||
sInstance = this;
|
||||
mLastMouseX = 0;
|
||||
mLastMouseY = 0;
|
||||
mStatusLock = new LLMutex(NULL);
|
||||
mStatusLock = new LLMutex();
|
||||
mModelPreview = NULL;
|
||||
|
||||
mLODMode[LLModel::LOD_HIGH] = 0;
|
||||
|
|
@ -1265,7 +1265,7 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp)
|
||||
: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex(NULL)
|
||||
: LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex()
|
||||
, mLodsQuery()
|
||||
, mLodsWithParsingError()
|
||||
, mPelvisZOffset( 0.0f )
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ LLMutex* LLLogChat::historyThreadsMutex()
|
|||
{
|
||||
if (sHistoryThreadsMutex == NULL)
|
||||
{
|
||||
sHistoryThreadsMutex = new LLMutex(NULL);
|
||||
sHistoryThreadsMutex = new LLMutex();
|
||||
}
|
||||
return sHistoryThreadsMutex;
|
||||
}
|
||||
|
|
@ -1012,8 +1012,8 @@ void LLDeleteHistoryThread::run()
|
|||
|
||||
LLActionThread::LLActionThread(const std::string& name)
|
||||
: LLThread(name),
|
||||
mMutex(NULL),
|
||||
mRunCondition(NULL),
|
||||
mMutex(),
|
||||
mRunCondition(),
|
||||
mFinished(false)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -830,9 +830,9 @@ LLMeshRepoThread::LLMeshRepoThread()
|
|||
{
|
||||
LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
|
||||
|
||||
mMutex = new LLMutex(NULL);
|
||||
mHeaderMutex = new LLMutex(NULL);
|
||||
mSignal = new LLCondition(NULL);
|
||||
mMutex = new LLMutex();
|
||||
mHeaderMutex = new LLMutex();
|
||||
mSignal = new LLCondition();
|
||||
mHttpRequest = new LLCore::HttpRequest;
|
||||
mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions);
|
||||
mHttpOptions->setTransferTimeout(SMALL_MESH_XFER_TIMEOUT);
|
||||
|
|
@ -2039,7 +2039,7 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
|
|||
mUploadSkin = upload_skin;
|
||||
mUploadJoints = upload_joints;
|
||||
mLockScaleIfJointPosition = lock_scale_if_joint_position;
|
||||
mMutex = new LLMutex(NULL);
|
||||
mMutex = new LLMutex();
|
||||
mPendingUploads = 0;
|
||||
mFinished = false;
|
||||
mOrigin = gAgent.getPositionAgent();
|
||||
|
|
@ -3446,7 +3446,7 @@ LLMeshRepository::LLMeshRepository()
|
|||
|
||||
void LLMeshRepository::init()
|
||||
{
|
||||
mMeshMutex = new LLMutex(NULL);
|
||||
mMeshMutex = new LLMutex();
|
||||
|
||||
LLConvexDecomposition::getInstance()->initSystem();
|
||||
|
||||
|
|
@ -4588,8 +4588,8 @@ LLPhysicsDecomp::LLPhysicsDecomp()
|
|||
mQuitting = false;
|
||||
mDone = false;
|
||||
|
||||
mSignal = new LLCondition(NULL);
|
||||
mMutex = new LLMutex(NULL);
|
||||
mSignal = new LLCondition();
|
||||
mMutex = new LLMutex();
|
||||
}
|
||||
|
||||
LLPhysicsDecomp::~LLPhysicsDecomp()
|
||||
|
|
|
|||
|
|
@ -825,10 +825,10 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted)
|
|||
|
||||
LLTextureCache::LLTextureCache(bool threaded)
|
||||
: LLWorkerThread("TextureCache", threaded),
|
||||
mWorkersMutex(NULL),
|
||||
mHeaderMutex(NULL),
|
||||
mListMutex(NULL),
|
||||
mFastCacheMutex(NULL),
|
||||
mWorkersMutex(),
|
||||
mHeaderMutex(),
|
||||
mListMutex(),
|
||||
mFastCacheMutex(),
|
||||
mHeaderAPRFile(NULL),
|
||||
mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called.
|
||||
mTexturesSizeTotal(0),
|
||||
|
|
|
|||
|
|
@ -925,7 +925,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
|
|||
mCanUseHTTP(true),
|
||||
mRetryAttempt(0),
|
||||
mActiveCount(0),
|
||||
mWorkMutex(NULL),
|
||||
mWorkMutex(),
|
||||
mFirstPacket(0),
|
||||
mLastPacket(-1),
|
||||
mTotalPackets(0),
|
||||
|
|
@ -2543,8 +2543,8 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
|
|||
mDebugPause(FALSE),
|
||||
mPacketCount(0),
|
||||
mBadPacketCount(0),
|
||||
mQueueMutex(getAPRPool()),
|
||||
mNetworkQueueMutex(getAPRPool()),
|
||||
mQueueMutex(),
|
||||
mNetworkQueueMutex(),
|
||||
mTextureCache(cache),
|
||||
mImageDecodeThread(imagedecodethread),
|
||||
mTextureBandwidth(0),
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ void LLFilePickerThread::run()
|
|||
//static
|
||||
void LLFilePickerThread::initClass()
|
||||
{
|
||||
sMutex = new LLMutex(NULL);
|
||||
sMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ void LLWatchdogTimeout::ping(const std::string& state)
|
|||
|
||||
// LLWatchdog
|
||||
LLWatchdog::LLWatchdog() :
|
||||
mSuspectsAccessMutex(NULL),
|
||||
mSuspectsAccessMutex(),
|
||||
mTimer(NULL),
|
||||
mLastClockCount(0),
|
||||
mKillerCallback(&default_killer_callback)
|
||||
|
|
@ -185,7 +185,7 @@ void LLWatchdog::init(killer_event_callback func)
|
|||
mKillerCallback = func;
|
||||
if(!mSuspectsAccessMutex && !mTimer)
|
||||
{
|
||||
mSuspectsAccessMutex = new LLMutex(NULL);
|
||||
mSuspectsAccessMutex = new LLMutex();
|
||||
mTimer = new LLWatchdogTimerThread();
|
||||
mTimer->setSleepTime(WATCHDOG_SLEEP_TIME_USEC / 1000);
|
||||
mLastClockCount = LLTimer::getTotalTime();
|
||||
|
|
|
|||
Loading…
Reference in New Issue