master
Nicky 2018-04-10 12:33:45 +02:00
commit 7cc408a5cd
42 changed files with 242 additions and 457 deletions

View File

@ -30,9 +30,9 @@
#include <map>
#include "llrun.h"
#include "llsd.h"
#include <atomic>
// Forward declarations
template <typename Type> class LLAtomic32;
typedef LLAtomic32<U32> LLAtomicU32;
class LLErrorThread;
class LLLiveFile;
#if LL_LINUX

View File

@ -33,8 +33,6 @@
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
@ -46,18 +44,10 @@ void ll_init_apr()
apr_initialize();
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)
{
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
}
LLThreadLocalPointerBase::initAllThreadLocalStorage();
gAPRInitialized = true;
@ -75,22 +65,8 @@ 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;
}
// Clean up the logging mutex
// All other threads NEED to be done before we clean up APR, so this is okay.
LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
@ -186,18 +162,14 @@ LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size
{
apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
mMutexp = new std::mutex();
}
}
LLVolatileAPRPool::~LLVolatileAPRPool()
{
//delete mutex
if(mMutexp)
{
apr_thread_mutex_destroy(mMutexp);
apr_pool_destroy(mMutexPool);
}
delete mMutexp;
mMutexp = nullptr;
}
//
@ -264,18 +236,12 @@ BOOL LLVolatileAPRPool::isFull()
//
// LLScopedLock
//
LLScopedLock::LLScopedLock(apr_thread_mutex_t* mutex) : mMutex(mutex)
LLScopedLock::LLScopedLock(std::mutex* mutex) : mMutex(mutex)
{
if(mutex)
{
if(ll_apr_warn_status(apr_thread_mutex_lock(mMutex)))
{
mLocked = false;
}
else
{
mLocked = true;
}
mutex->lock();
mLocked = true;
}
else
{
@ -292,10 +258,7 @@ void LLScopedLock::unlock()
{
if(mLocked)
{
if(!ll_apr_warn_status(apr_thread_mutex_unlock(mMutex)))
{
mLocked = false;
}
mMutex->unlock();
}
}

View File

@ -36,16 +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 <atomic>
#if LL_WINDOWS
#pragma warning(disable:4265)
#endif
#include <mutex>
#if LL_WINDOWS
#pragma warning(default:4265)
#endif
#include "llstring.h"
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
struct apr_dso_handle_t;
/**
* @brief Function which appropriately logs error or remains quiet on
@ -120,7 +127,7 @@ 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;
std::mutex *mMutexp;
apr_pool_t *mMutexPool;
} ;
@ -142,7 +149,7 @@ public:
* @param mutex An allocated APR mutex. If you pass in NULL,
* this wrapper will not lock.
*/
LLScopedLock(apr_thread_mutex_t* mutex);
LLScopedLock( std::mutex* mutex );
/**
* @brief Destructor which unlocks the mutex if still locked.
@ -161,35 +168,43 @@ public:
protected:
bool mLocked;
apr_thread_mutex_t* mMutex;
std::mutex* mMutex;
};
template <typename Type> class LLAtomic32
template <typename Type, typename AtomicType = std::atomic< Type > > class LLAtomicBase
{
public:
LLAtomic32<Type>() {};
LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
~LLAtomic32<Type>() {};
LLAtomicBase() {};
LLAtomicBase( Type x ) { mData.store( x ); };
~LLAtomicBase() {};
operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
operator const Type() { return mData; }
Type CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); }
Type CurrentValue() const { return mData; }
Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
Type operator =( Type x) { mData.store( x ); return mData; }
void operator -=(Type x) { mData -= x; }
void operator +=(Type x) { mData += x; }
Type operator ++(int) { return mData++; }
Type operator --(int) { return mData--; }
Type operator ++() { return apr_atomic_inc32(&mData); } // Type++
Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
Type operator ++() { return ++mData; }
Type operator --() { return --mData; }
private:
volatile apr_uint32_t mData;
AtomicType mData;
};
typedef LLAtomic32<U32> LLAtomicU32;
typedef LLAtomic32<S32> LLAtomicS32;
// ND: Typedefs for specialized versions. Using std::atomic_(u)int32_t to get the optimzed implementation.
#ifndef LL_LINUX
typedef LLAtomicBase<U32, std::atomic_uint32_t> LLAtomicU32;
typedef LLAtomicBase<S32, std::atomic_int32_t> LLAtomicS32;
#else
typedef LLAtomicBase<U32, std::atomic_uint> LLAtomicU32;
typedef LLAtomicBase<S32, std::atomic_int> LLAtomicS32;
#endif
typedef LLAtomicBase<bool, std::atomic_bool> LLAtomicBool;
// File IO convenience functions.
// Returns NULL if the file fails to open, sets *sizep to file size if not NULL

View File

@ -54,6 +54,9 @@
#include "nd/ndlogthrottle.h"
namespace {
LLMutex gLogMutex;
LLMutex gCallStacksLogMutex ;
#if LL_WINDOWS
void debugger_print(const std::string& s)
{
@ -417,7 +420,7 @@ namespace
namespace LLError
{
class SettingsConfig : public LLRefCount
class SettingsConfig: public LLRefCount
{
friend class Settings;
@ -1035,64 +1038,14 @@ 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
{
bool Log::shouldLog(CallSite& site)
{
LogLock lock;
if (!lock.ok())
LLMutexTrylock lock( &gLogMutex,5);
if (!lock.isLocked() )
{
return false;
}
@ -1142,11 +1095,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();
@ -1162,8 +1115,8 @@ namespace LLError
void Log::flush(std::ostringstream* out, char* message)
{
LogLock lock;
if (!lock.ok())
LLMutexTrylock lock(&gLogMutex,5);
if (!lock.isLocked())
{
return;
}
@ -1202,8 +1155,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;
}

View File

@ -30,8 +30,7 @@
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
: LLLineBuffer(),
mMaxLines(max_lines),
mMutex(NULL)
mMaxLines(max_lines)
{
mTimer.reset();
}

View File

@ -36,17 +36,16 @@
void LLInstanceTrackerBase::StaticBase::incrementDepth()
{
apr_atomic_inc32(&sIterationNestDepth);
++sIterationNestDepth;
}
void LLInstanceTrackerBase::StaticBase::decrementDepth()
{
llassert(sIterationNestDepth);
apr_atomic_dec32(&sIterationNestDepth);
--sIterationNestDepth;
}
U32 LLInstanceTrackerBase::StaticBase::getDepth()
{
apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth);
return data;
return sIterationNestDepth;
}

View File

@ -31,6 +31,7 @@
#include <map>
#include <typeinfo>
#include <atomic>
#include "llstringtable.h"
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
@ -119,7 +120,11 @@ protected:
void decrementDepth();
U32 getDepth();
private:
U32 sIterationNestDepth;
#ifndef LL_LINUX
std::atomic_uint32_t sIterationNestDepth;
#else
std::atomic_uint sIterationNestDepth;
#endif
};
};

View File

@ -1122,7 +1122,7 @@ LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type, U32 max_pool_size) :
{
if(type == STATIC_THREADED || type == VOLATILE_THREADED)
{
mMutexp = new LLMutex(NULL) ;
mMutexp = new LLMutex() ;
}
for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++)

View File

@ -33,20 +33,9 @@
//============================================================================
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);
}
@ -56,15 +45,6 @@ LLMutex::~LLMutex()
//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 +56,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 +86,16 @@ 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,12 +118,9 @@ 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;
}
#if MUTEX_DEBUG
// Have to have the lock before we can access the debug info
U32 id = LLThread::currentID();
@ -161,44 +135,28 @@ bool LLMutex::trylock()
//============================================================================
LLCondition::LLCondition(apr_pool_t *poolp) :
LLMutex(poolp)
LLCondition::LLCondition()
{
// 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();
}

View File

@ -28,10 +28,18 @@
#define LL_LLMUTEX_H
#include "stdtypes.h"
#if !LL_WINDOWS
#include <stdint.h>
#include "lltimer.h"
#if LL_WINDOWS
#pragma warning(disable:4265)
#endif
#include <mutex>
#include <condition_variable>
#if LL_WINDOWS
#pragma warning(default:4265)
#endif
//============================================================================
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
@ -40,9 +48,6 @@
#include <map>
#endif
struct apr_thread_mutex_t;
struct apr_pool_t;
struct apr_thread_cond_t;
class LL_COMMON_API LLMutex
{
@ -52,7 +57,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(); // NULL pool constructs a new pool for the mutex
virtual ~LLMutex();
void lock(); // blocks
@ -63,12 +68,11 @@ 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;
bool mIsLocalPool;
#if MUTEX_DEBUG
std::map<U32, BOOL> mIsLocked;
@ -79,7 +83,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(); // Defaults to global pool, could use the thread pool as well.
~LLCondition();
void wait(); // blocks
@ -87,7 +91,7 @@ public:
void broadcast();
protected:
apr_thread_cond_t* mAPRCondp;
std::condition_variable mCond;
};
class LLMutexLock
@ -129,6 +133,23 @@ public:
if (mMutex)
mLocked = mMutex->trylock();
}
LLMutexTrylock( LLMutex* mutex, U32 aTries )
: mMutex( mutex ),
mLocked( false )
{
if( !mMutex )
return;
U32 i = 0;
while( i < aTries )
{
mLocked = mMutex->trylock();
if( mLocked )
break;
++i;
ms_sleep( 10 );
}
}
~LLMutexTrylock()
{

View File

@ -36,10 +36,10 @@
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
LLThread(name),
mThreaded(threaded),
mIdleThread(TRUE),
mNextHandle(0),
mStarted(FALSE)
{
mIdleThread = true;
if (mThreaded)
{
if(should_pause)

View File

@ -128,7 +128,7 @@ public:
};
protected:
LLAtomic32<status_t> mStatus;
LLAtomicBase<status_t> mStatus;
U32 mPriority;
U32 mFlags;
};
@ -198,7 +198,7 @@ public:
protected:
BOOL mThreaded; // if false, run on main thread and do updates during update()
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
LLAtomicBool mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
request_queue_t mRequestQueue;

View File

@ -158,7 +158,7 @@ public:
}
private:
LLAtomic32< S32 > mRef;
LLAtomicS32 mRef;
};
/**

View File

@ -116,29 +116,27 @@ void LLThread::registerThreadID()
//
// Handed to the APR thread creation function
//
void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
void LLThread::threadRun()
{
LLThread *threadp = (LLThread *)datap;
#ifdef LL_WINDOWS
set_thread_name(-1, threadp->mName.c_str());
set_thread_name( -1, mName.c_str() );
#endif
// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
mRecorder = new LLTrace::ThreadRecorder( *LLTrace::get_master_thread_recorder() );
sThreadID = threadp->mID;
sThreadID = mID;
// Run the user supplied function
do
{
try
{
threadp->run();
run();
}
catch (const LLContinueError &e)
{
LL_WARNS("THREAD") << "ContinueException on thread '" << threadp->mName <<
LL_WARNS( "THREAD" ) << "ContinueException on thread '" << mName <<
"' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
//output possible call stacks to log file.
LLError::LLCallStacks::print();
@ -154,37 +152,26 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
// We're done with the run function, this thread is done executing now.
//NB: we are using this flag to sync across threads...we really need memory barriers here
threadp->mStatus = STOPPED;
mStatus = STOPPED;
delete threadp->mRecorder;
threadp->mRecorder = NULL;
delete mRecorder;
mRecorder = nullptr;
return NULL;
return;
}
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(FALSE),
mName(name),
mAPRThreadp(NULL),
mThreadp(NULL),
mStatus(STOPPED),
mRecorder(NULL)
{
mID = ++sIDIter;
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
if (poolp)
{
mIsLocalPool = FALSE;
mAPRPoolp = poolp;
}
else
{
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 ;
}
@ -214,7 +201,7 @@ void LLThread::shutdown()
// Warning! If you somehow call the thread destructor from itself,
// the thread will die in an unclean fashion!
if (mAPRThreadp)
if( mThreadp )
{
if (!isStopped())
{
@ -248,10 +235,12 @@ void LLThread::shutdown()
// Put a stake in its heart.
delete mRecorder;
apr_thread_exit(mAPRThreadp, -1);
// ND: There is no such thing as to terminate a std::thread, we detach it so no wait will happen.
// Otherwise craft something platform specific with std::thread::native_handle
mThreadp->detach();
return;
}
mAPRThreadp = NULL;
mThreadp = NULL;
}
delete mRunCondition;
@ -260,12 +249,6 @@ void LLThread::shutdown()
delete mDataLock;
mDataLock = NULL;
if (mIsLocalPool && mAPRPoolp)
{
apr_pool_destroy(mAPRPoolp);
mAPRPoolp = 0;
}
if (mRecorder)
{
// missed chance to properly shut down recorder (needs to be done in thread context)
@ -283,21 +266,16 @@ void LLThread::start()
// Set thread state to running
mStatus = RUNNING;
apr_status_t status =
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
if(status == APR_SUCCESS)
{
// We won't bother joining
apr_thread_detach(mAPRThreadp);
try
{
mThreadp = new std::thread( std::bind( &LLThread::threadRun, this ) );
//mThreadp->detach();
}
catch( std::system_error& ex )
{
mStatus = STOPPED;
LL_WARNS() << "failed to start thread " << mName << " " << ex.what() << LL_ENDL;
}
else
{
mStatus = STOPPED;
LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
ll_apr_warn_status(status);
}
}
//============================================================================
@ -372,11 +350,7 @@ U32 LLThread::currentID()
// static
void LLThread::yield()
{
#if LL_LINUX || LL_SOLARIS
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
#else
apr_thread_yield();
#endif
std::this_thread::yield();
}
void LLThread::wake()
@ -409,7 +383,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
{
if (!sMutex)
{
sMutex = new LLMutex(0);
sMutex = new LLMutex();
}
}
@ -417,7 +391,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
{
delete sMutex;
sMutex = NULL;
sMutex = nullptr;
}

View File

@ -34,6 +34,8 @@
#include "llmutex.h"
#include "llrefcount.h"
#include <thread>
LL_COMMON_API void assert_main_thread();
namespace LLTrace
@ -86,7 +88,6 @@ public:
// this kicks off the apr thread
void start(void);
apr_pool_t *getAPRPool() { return mAPRPoolp; }
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
U32 getID() const { return mID; }
@ -97,19 +98,16 @@ public:
static void registerThreadID();
private:
BOOL mPaused;
bool mPaused;
// static function passed to APR thread creation routine
static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
void threadRun( );
protected:
std::string mName;
class LLCondition* mRunCondition;
LLMutex* mDataLock;
apr_thread_t *mAPRThreadp;
apr_pool_t *mAPRPoolp;
BOOL mIsLocalPool;
std::thread *mThreadp;
EThreadStatus mStatus;
U32 mID;
LLTrace::ThreadRecorder* mRecorder;

View File

@ -24,87 +24,5 @@
*/
#include "linden_common.h"
#include <apr_pools.h>
#include <apr_queue.h>
#include "llthreadsafequeue.h"
#include "llexception.h"
// LLThreadSafeQueueImplementation
//-----------------------------------------------------------------------------
LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity):
mOwnsPool(pool == 0),
mPool(pool),
mQueue(0)
{
if(mOwnsPool) {
apr_status_t status = apr_pool_create(&mPool, 0);
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate pool"));
} else {
; // No op.
}
apr_status_t status = apr_queue_create(&mQueue, capacity, mPool);
if(status != APR_SUCCESS) LLTHROW(LLThreadSafeQueueError("failed to allocate queue"));
}
LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
{
if(mQueue != 0) {
if(apr_queue_size(mQueue) != 0) LL_WARNS() <<
"terminating queue which still contains " << apr_queue_size(mQueue) <<
" elements;" << "memory will be leaked" << LL_ENDL;
apr_queue_term(mQueue);
}
if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool);
}
void LLThreadSafeQueueImplementation::pushFront(void * element)
{
apr_status_t status = apr_queue_push(mQueue, element);
if(status == APR_EINTR) {
LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
LLTHROW(LLThreadSafeQueueError("push failed"));
} else {
; // Success.
}
}
bool LLThreadSafeQueueImplementation::tryPushFront(void * element){
return apr_queue_trypush(mQueue, element) == APR_SUCCESS;
}
void * LLThreadSafeQueueImplementation::popBack(void)
{
void * element;
apr_status_t status = apr_queue_pop(mQueue, &element);
if(status == APR_EINTR) {
LLTHROW(LLThreadSafeQueueInterrupt());
} else if(status != APR_SUCCESS) {
LLTHROW(LLThreadSafeQueueError("pop failed"));
} else {
return element;
}
}
bool LLThreadSafeQueueImplementation::tryPopBack(void *& element)
{
return apr_queue_trypop(mQueue, &element) == APR_SUCCESS;
}
size_t LLThreadSafeQueueImplementation::size()
{
return apr_queue_size(mQueue);
}

View File

@ -28,12 +28,10 @@
#define LL_LLTHREADSAFEQUEUE_H
#include "llexception.h"
#include "llmutex.h"
#include "lltimer.h"
#include <string>
struct apr_pool_t; // From apr_pools.h
class LLThreadSafeQueueImplementation; // See below.
#include <deque>
//
// A general queue exception.
@ -65,29 +63,6 @@ public:
};
struct apr_queue_t; // From apr_queue.h
//
// Implementation details.
//
class LL_COMMON_API LLThreadSafeQueueImplementation
{
public:
LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity);
~LLThreadSafeQueueImplementation();
void pushFront(void * element);
bool tryPushFront(void * element);
void * popBack(void);
bool tryPopBack(void *& element);
size_t size();
private:
bool mOwnsPool;
apr_pool_t * mPool;
apr_queue_t * mQueue;
};
//
// Implements a thread safe FIFO.
@ -100,7 +75,7 @@ public:
// If the pool is set to NULL one will be allocated and managed by this
// queue.
LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024);
LLThreadSafeQueue( U32 capacity = 1024);
// Add an element to the front of queue (will block if the queue has
// reached capacity).
@ -128,7 +103,9 @@ public:
size_t size();
private:
LLThreadSafeQueueImplementation mImplementation;
std::deque< ElementT > mStorage;
LLCondition mLock;;
U32 mCapacity; // Really needed?
};
@ -138,8 +115,8 @@ private:
template<typename ElementT>
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity):
mImplementation(pool, capacity)
LLThreadSafeQueue<ElementT>::LLThreadSafeQueue( U32 capacity):
mCapacity( capacity )
{
; // No op.
}
@ -148,12 +125,18 @@ LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int c
template<typename ElementT>
void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
{
ElementT * elementCopy = new ElementT(element);
try {
mImplementation.pushFront(elementCopy);
} catch (LLThreadSafeQueueInterrupt) {
delete elementCopy;
throw;
while( true )
{
{
LLMutexLock lck( &mLock );
if( mStorage.size() < mCapacity )
{
mStorage.push_front( element );
mLock.signal();
return;
}
}
ms_sleep( 100 );
}
}
@ -161,43 +144,58 @@ void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
template<typename ElementT>
bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
{
ElementT * elementCopy = new ElementT(element);
bool result = mImplementation.tryPushFront(elementCopy);
if(!result) delete elementCopy;
return result;
LLMutexTrylock lck( &mLock );
if( !lck.isLocked() )
return false;
if( mStorage.size() >= mCapacity )
return false;
mStorage.push_front( element );
mLock.signal();
return true;
}
template<typename ElementT>
ElementT LLThreadSafeQueue<ElementT>::popBack(void)
{
ElementT * element = reinterpret_cast<ElementT *> (mImplementation.popBack());
ElementT result(*element);
delete element;
return result;
while( true )
{
mLock.wait();
if( !mStorage.empty() )
{
ElementT value = mStorage.back();
mStorage.pop_back();
return value;
}
}
}
template<typename ElementT>
bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element)
{
void * storedElement;
bool result = mImplementation.tryPopBack(storedElement);
if(result) {
ElementT * elementPtr = reinterpret_cast<ElementT *>(storedElement);
element = *elementPtr;
delete elementPtr;
} else {
; // No op.
}
return result;
LLMutexTrylock lck( &mLock );
if( !lck.isLocked() )
return false;
if( mStorage.empty() )
return false;
element = mStorage.back();
mStorage.pop_back();
return true;
}
template<typename ElementT>
size_t LLThreadSafeQueue<ElementT>::size(void)
{
return mImplementation.size();
// Nicky: apr_queue_size is/was NOT threadsafe. I still play it safe here and rather lock the storage
LLMutexLock lck( &mLock );
return mStorage.size();
}

View File

@ -739,7 +739,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};

View File

@ -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,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
mWorkerClassName(name),
mRequestHandle(LLWorkerThread::nullHandle()),
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
mMutex(NULL),
mWorkFlags(0)
{
if (!mWorkerThread)

View File

@ -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);

View File

@ -610,7 +610,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();
LLImageBase::createPrivatePool() ;
}

View File

@ -35,7 +35,7 @@
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
: LLQueuedThread("imagedecode", threaded)
{
mCreationMutex = new LLMutex(getAPRPool());
mCreationMutex = new LLMutex();
}
//virtual

View File

@ -214,7 +214,7 @@ void LLVolumeMgr::useMutex()
{
if (!mDataMutex)
{
mDataMutex = new LLMutex(gAPRPoolp);
mDataMutex = new LLMutex();
}
}

View File

@ -265,7 +265,7 @@ void LLBufferArray::setThreaded(bool threaded)
{
if(!mMutexp)
{
mMutexp = new LLMutex(NULL);
mMutexp = new LLMutex();
}
}
else

View File

@ -48,7 +48,6 @@ static void tcp_close_channel(LLSocket::ptr_t* handle_ptr); // Close an open TCP
LLProxy::LLProxy():
mHTTPProxyEnabled(false),
mProxyMutex(NULL),
mUDPProxy(),
mTCPProxy(),
mHTTPProxy(),

View File

@ -298,7 +298,7 @@ private:
private:
// Is the HTTP proxy enabled? Safe to read in any thread, but do not write directly.
// Instead use enableHTTPProxy() and disableHTTPProxy() instead.
mutable LLAtomic32<bool> mHTTPProxyEnabled;
mutable LLAtomicBool mHTTPProxyEnabled;
// Mutex to protect shared members in non-main thread calls to applyProxySettings().
mutable LLMutex mProxyMutex;

View File

@ -394,8 +394,8 @@ protected:
S32 mCurrentPoolReallocCount;
#if LL_THREADS_APR
apr_thread_mutex_t* mChainsMutex;
apr_thread_mutex_t* mCallbackMutex;
std::mutex* mChainsMutex;
std::mutex* mCallbackMutex;
#else
int* mChainsMutex;
int* mCallbackMutex;

View File

@ -92,8 +92,6 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)
}
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
mInputMutex(gAPRPoolp),
mOutputMutex(gAPRPoolp),
mOutputStartIndex(0),
mOwner(owner),
mSocket(socket)

View File

@ -81,12 +81,11 @@ protected:
};
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
mIncomingQueueMutex(gAPRPoolp)
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
{
if(!sInstancesMutex)
{
sInstancesMutex = new LLMutex(gAPRPoolp);
sInstancesMutex = new LLMutex();
}
mOwner = owner;

View File

@ -155,7 +155,6 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL
int main(int argc, char **argv)
#endif
{
ll_init_apr();
// Set up llerror logging

View File

@ -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++)

View File

@ -2510,7 +2510,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();
}

View File

@ -58,7 +58,6 @@ 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),
mShowHistory(false),
mMessages(NULL),
mHistoryThreadsBusy(false),

View File

@ -267,7 +267,7 @@ mCalculateBtn(NULL)
sInstance = this;
mLastMouseX = 0;
mLastMouseY = 0;
mStatusLock = new LLMutex(NULL);
mStatusLock = new LLMutex();
mModelPreview = NULL;
mLODMode[LLModel::LOD_HIGH] = 0;
@ -1268,7 +1268,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)
, mLodsQuery()
, mLodsWithParsingError()
, mPelvisZOffset( 0.0f )

View File

@ -603,7 +603,7 @@ LLMutex* LLLogChat::historyThreadsMutex()
{
if (sHistoryThreadsMutex == NULL)
{
sHistoryThreadsMutex = new LLMutex(NULL);
sHistoryThreadsMutex = new LLMutex();
}
return sHistoryThreadsMutex;
}
@ -1196,8 +1196,6 @@ void LLDeleteHistoryThread::run()
LLActionThread::LLActionThread(const std::string& name)
: LLThread(name),
mMutex(NULL),
mRunCondition(NULL),
mFinished(false)
{
}

View File

@ -46,7 +46,7 @@ void LLMainLoopRepeater::start(void)
{
if(mQueue != 0) return;
mQueue = new LLThreadSafeQueue<LLSD>(gAPRPoolp, 1024);
mQueue = new LLThreadSafeQueue<LLSD>( 1024);
mMainLoopConnection = LLEventPumps::instance().
obtain("mainloop").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1));
mRepeaterConnection = LLEventPumps::instance().

View File

@ -823,9 +823,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);
@ -2004,7 +2004,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();
@ -3405,7 +3405,7 @@ LLMeshRepository::LLMeshRepository()
void LLMeshRepository::init()
{
mMeshMutex = new LLMutex(NULL);
mMeshMutex = new LLMutex();
LLConvexDecomposition::getInstance()->initSystem();
@ -4379,8 +4379,8 @@ LLPhysicsDecomp::LLPhysicsDecomp()
mQuitting = false;
mDone = false;
mSignal = new LLCondition(NULL);
mMutex = new LLMutex(NULL);
mSignal = new LLCondition();
mMutex = new LLMutex();
}
LLPhysicsDecomp::~LLPhysicsDecomp()

View File

@ -825,10 +825,6 @@ void LLTextureCacheWorker::endWork(S32 param, bool aborted)
LLTextureCache::LLTextureCache(bool threaded)
: LLWorkerThread("TextureCache", threaded),
mWorkersMutex(NULL),
mHeaderMutex(NULL),
mListMutex(NULL),
mFastCacheMutex(NULL),
mHeaderAPRFile(NULL),
mReadOnly(TRUE), //do not allow to change the texture cache until setReadOnly() is called.
mTexturesSizeTotal(0),

View File

@ -223,7 +223,7 @@ private:
typedef std::map<LLUUID,S32> size_map_t;
size_map_t mTexturesSizeMap;
S64 mTexturesSizeTotal;
LLAtomic32<BOOL> mDoPurge;
LLAtomicBool mDoPurge;
typedef std::map<S32, Entry> idx_entry_map_t;
idx_entry_map_t mUpdatedEntryMap;

View File

@ -928,7 +928,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mCanUseHTTP(true),
mRetryAttempt(0),
mActiveCount(0),
mWorkMutex(NULL),
mFirstPacket(0),
mLastPacket(-1),
mTotalPackets(0),
@ -2564,8 +2563,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mDebugPause(FALSE),
mPacketCount(0),
mBadPacketCount(0),
mQueueMutex(getAPRPool()),
mNetworkQueueMutex(getAPRPool()),
mTextureCache(cache),
mImageDecodeThread(imagedecodethread),
mTextureBandwidth(0),

View File

@ -240,7 +240,7 @@ void LLGenericLoadMultipleFilePicker::notify(std::list<std::string> filenames)
//static
void LLFilePickerThread::initClass()
{
sMutex = new LLMutex(NULL);
sMutex = new LLMutex();
}
//static

View File

@ -192,7 +192,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();