diff options
Diffstat (limited to 'indra/llcommon')
| -rw-r--r-- | indra/llcommon/llthread.h | 570 | 
1 files changed, 285 insertions, 285 deletions
| diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 5d5ecd62fc..4b6c3df105 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -1,285 +1,285 @@ -/** 
 - * @file llthread.h
 - * @brief Base classes for thread, mutex and condition handling.
 - *
 - * $LicenseInfo:firstyear=2004&license=viewergpl$
 - * 
 - * Copyright (c) 2004-2009, Linden Research, Inc.
 - * 
 - * Second Life Viewer Source Code
 - * The source code in this file ("Source Code") is provided by Linden Lab
 - * to you under the terms of the GNU General Public License, version 2.0
 - * ("GPL"), unless you have obtained a separate licensing agreement
 - * ("Other License"), formally executed by you and Linden Lab.  Terms of
 - * the GPL can be found in doc/GPL-license.txt in this distribution, or
 - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
 - * 
 - * There are special exceptions to the terms and conditions of the GPL as
 - * it is applied to this Source Code. View the full text of the exception
 - * in the file doc/FLOSS-exception.txt in this software distribution, or
 - * online at
 - * http://secondlifegrid.net/programs/open_source/licensing/flossexception
 - * 
 - * By copying, modifying or distributing this software, you acknowledge
 - * that you have read and understood your obligations described above,
 - * and agree to abide by those obligations.
 - * 
 - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
 - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
 - * COMPLETENESS OR PERFORMANCE.
 - * $/LicenseInfo$
 - */
 -
 -#ifndef LL_LLTHREAD_H
 -#define LL_LLTHREAD_H
 -
 -#include "llapp.h"
 -#include "llapr.h"
 -#include "apr_thread_cond.h"
 -
 -class LLThread;
 -class LLMutex;
 -class LLCondition;
 -
 -#if LL_WINDOWS
 -#define ll_thread_local __declspec(thread)
 -#else
 -#define ll_thread_local __thread
 -#endif
 -
 -class LL_COMMON_API LLThread
 -{
 -private:
 -	static U32 sIDIter;
 -
 -public:
 -	typedef enum e_thread_status
 -	{
 -		STOPPED = 0,	// The thread is not running.  Not started, or has exited its run function
 -		RUNNING = 1,	// The thread is currently running
 -		QUITTING= 2 	// Someone wants this thread to quit
 -	} EThreadStatus;
 -
 -	LLThread(const std::string& name, apr_pool_t *poolp = NULL);
 -	virtual ~LLThread(); // Warning!  You almost NEVER want to destroy a thread unless it's in the STOPPED state.
 -	virtual void shutdown(); // stops the thread
 -	
 -	bool isQuitting() const { return (QUITTING == mStatus); }
 -	bool isStopped() const { return (STOPPED == mStatus); }
 -	
 -	static U32 currentID(); // Return ID of current thread
 -	static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
 -	
 -public:
 -	// PAUSE / RESUME functionality. See source code for important usage notes.
 -	// Called from MAIN THREAD.
 -	void pause();
 -	void unpause();
 -	bool isPaused() { return isStopped() || mPaused == TRUE; }
 -	
 -	// Cause the thread to wake up and check its condition
 -	void wake();
 -
 -	// Same as above, but to be used when the condition is already locked.
 -	void wakeLocked();
 -
 -	// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
 -	void checkPause();
 -
 -	// this kicks off the apr thread
 -	void start(void);
 -
 -	apr_pool_t *getAPRPool() { return mAPRPoolp; }
 -	LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
 -
 -	U32 getID() const { return mID; }
 -
 -private:
 -	BOOL				mPaused;
 -	
 -	// static function passed to APR thread creation routine
 -	static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
 -
 -protected:
 -	std::string			mName;
 -	LLCondition*		mRunCondition;
 -
 -	apr_thread_t		*mAPRThreadp;
 -	apr_pool_t			*mAPRPoolp;
 -	BOOL				mIsLocalPool;
 -	EThreadStatus		mStatus;
 -	U32					mID;
 -
 -	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 -	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
 -	//      otherwise it will cause severe memory leaking!!! --bao
 -	LLVolatileAPRPool  *mLocalAPRFilePoolp ; 
 -
 -	void setQuitting();
 -	
 -	// virtual function overridden by subclass -- this will be called when the thread runs
 -	virtual void run(void) = 0; 
 -	
 -	// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
 -	virtual bool runCondition(void);
 -
 -	// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
 -	inline void lockData();
 -	inline void unlockData();
 -	
 -	// This is the predicate that decides whether the thread should sleep.  
 -	// It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access
 -	// data structures that are thread-unsafe.
 -	bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
 -
 -	// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
 -	// mRunCondition->lock();
 -	// if(!shouldSleep())
 -	//     mRunCondition->signal();
 -	// mRunCondition->unlock();
 -};
 -
 -//============================================================================
 -
 -#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
 -
 -class LL_COMMON_API LLMutex
 -{
 -public:
 -	typedef enum
 -	{
 -		NO_THREAD = 0xFFFFFFFF
 -	} e_locking_thread;
 -
 -	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
 -	~LLMutex();
 -	
 -	void lock();		// blocks
 -	void unlock();
 -	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
 -	U32 lockingThread() const; //get ID of locking thread
 -	
 -protected:
 -	apr_thread_mutex_t *mAPRMutexp;
 -	mutable U32			mCount;
 -	mutable U32			mLockingThread;
 -	
 -	apr_pool_t			*mAPRPoolp;
 -	BOOL				mIsLocalPool;
 -	
 -#if MUTEX_DEBUG
 -	std::map<U32, BOOL> mIsLocked;
 -#endif
 -};
 -
 -// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
 -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();
 -	
 -	void wait();		// blocks
 -	void signal();
 -	void broadcast();
 -	
 -protected:
 -	apr_thread_cond_t *mAPRCondp;
 -};
 -
 -class LLMutexLock
 -{
 -public:
 -	LLMutexLock(LLMutex* mutex)
 -	{
 -		mMutex = mutex;
 -		mMutex->lock();
 -	}
 -	~LLMutexLock()
 -	{
 -		mMutex->unlock();
 -	}
 -private:
 -	LLMutex* mMutex;
 -};
 -
 -//============================================================================
 -
 -void LLThread::lockData()
 -{
 -	mRunCondition->lock();
 -}
 -
 -void LLThread::unlockData()
 -{
 -	mRunCondition->unlock();
 -}
 -
 -
 -//============================================================================
 -
 -// see llmemory.h for LLPointer<> definition
 -
 -class LL_COMMON_API LLThreadSafeRefCount
 -{
 -public:
 -	static void initThreadSafeRefCount(); // creates sMutex
 -	static void cleanupThreadSafeRefCount(); // destroys sMutex
 -	
 -private:
 -	static LLMutex* sMutex;
 -
 -private:
 -	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
 -	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
 -
 -protected:
 -	virtual ~LLThreadSafeRefCount(); // use unref()
 -	
 -public:
 -	LLThreadSafeRefCount();
 -	
 -	void ref()
 -	{
 -		if (sMutex) sMutex->lock();
 -		mRef++; 
 -		if (sMutex) sMutex->unlock();
 -	} 
 -
 -	S32 unref()
 -	{
 -		llassert(mRef >= 1);
 -		if (sMutex) sMutex->lock();
 -		S32 res = --mRef;
 -		if (sMutex) sMutex->unlock();
 -		if (0 == res) 
 -		{
 -			delete this; 
 -			return 0;
 -		}
 -		return res;
 -	}	
 -	S32 getNumRefs() const
 -	{
 -		return mRef;
 -	}
 -
 -private: 
 -	S32	mRef; 
 -};
 -
 -//============================================================================
 -
 -// Simple responder for self destructing callbacks
 -// Pure virtual class
 -class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
 -{
 -protected:
 -	virtual ~LLResponder();
 -public:
 -	virtual void completed(bool success) = 0;
 -};
 -
 -//============================================================================
 -
 -#endif // LL_LLTHREAD_H
 +/**  + * @file llthread.h + * @brief Base classes for thread, mutex and condition handling. + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + *  + * Copyright (c) 2004-2009, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLTHREAD_H +#define LL_LLTHREAD_H + +#include "llapp.h" +#include "llapr.h" +#include "apr_thread_cond.h" + +class LLThread; +class LLMutex; +class LLCondition; + +#if LL_WINDOWS +#define ll_thread_local __declspec(thread) +#else +#define ll_thread_local __thread +#endif + +class LL_COMMON_API LLThread +{ +private: +	static U32 sIDIter; + +public: +	typedef enum e_thread_status +	{ +		STOPPED = 0,	// The thread is not running.  Not started, or has exited its run function +		RUNNING = 1,	// The thread is currently running +		QUITTING= 2 	// Someone wants this thread to quit +	} EThreadStatus; + +	LLThread(const std::string& name, apr_pool_t *poolp = NULL); +	virtual ~LLThread(); // Warning!  You almost NEVER want to destroy a thread unless it's in the STOPPED state. +	virtual void shutdown(); // stops the thread +	 +	bool isQuitting() const { return (QUITTING == mStatus); } +	bool isStopped() const { return (STOPPED == mStatus); } +	 +	static U32 currentID(); // Return ID of current thread +	static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. +	 +public: +	// PAUSE / RESUME functionality. See source code for important usage notes. +	// Called from MAIN THREAD. +	void pause(); +	void unpause(); +	bool isPaused() { return isStopped() || mPaused == TRUE; } +	 +	// Cause the thread to wake up and check its condition +	void wake(); + +	// Same as above, but to be used when the condition is already locked. +	void wakeLocked(); + +	// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused. +	void checkPause(); + +	// this kicks off the apr thread +	void start(void); + +	apr_pool_t *getAPRPool() { return mAPRPoolp; } +	LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; } + +	U32 getID() const { return mID; } + +private: +	BOOL				mPaused; +	 +	// static function passed to APR thread creation routine +	static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap); + +protected: +	std::string			mName; +	LLCondition*		mRunCondition; + +	apr_thread_t		*mAPRThreadp; +	apr_pool_t			*mAPRPoolp; +	BOOL				mIsLocalPool; +	EThreadStatus		mStatus; +	U32					mID; + +	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used. +	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. +	//      otherwise it will cause severe memory leaking!!! --bao +	LLVolatileAPRPool  *mLocalAPRFilePoolp ;  + +	void setQuitting(); +	 +	// virtual function overridden by subclass -- this will be called when the thread runs +	virtual void run(void) = 0;  +	 +	// virtual predicate function -- returns true if the thread should wake up, false if it should sleep. +	virtual bool runCondition(void); + +	// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition() +	inline void lockData(); +	inline void unlockData(); +	 +	// This is the predicate that decides whether the thread should sleep.   +	// It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access +	// data structures that are thread-unsafe. +	bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); } + +	// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following: +	// mRunCondition->lock(); +	// if(!shouldSleep()) +	//     mRunCondition->signal(); +	// mRunCondition->unlock(); +}; + +//============================================================================ + +#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO) + +class LL_COMMON_API LLMutex +{ +public: +	typedef enum +	{ +		NO_THREAD = 0xFFFFFFFF +	} e_locking_thread; + +	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex +	~LLMutex(); +	 +	void lock();		// blocks +	void unlock(); +	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free +	U32 lockingThread() const; //get ID of locking thread +	 +protected: +	apr_thread_mutex_t *mAPRMutexp; +	mutable U32			mCount; +	mutable U32			mLockingThread; +	 +	apr_pool_t			*mAPRPoolp; +	BOOL				mIsLocalPool; +	 +#if MUTEX_DEBUG +	std::map<U32, BOOL> mIsLocked; +#endif +}; + +// Actually a condition/mutex pair (since each condition needs to be associated with a mutex). +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(); +	 +	void wait();		// blocks +	void signal(); +	void broadcast(); +	 +protected: +	apr_thread_cond_t *mAPRCondp; +}; + +class LLMutexLock +{ +public: +	LLMutexLock(LLMutex* mutex) +	{ +		mMutex = mutex; +		mMutex->lock(); +	} +	~LLMutexLock() +	{ +		mMutex->unlock(); +	} +private: +	LLMutex* mMutex; +}; + +//============================================================================ + +void LLThread::lockData() +{ +	mRunCondition->lock(); +} + +void LLThread::unlockData() +{ +	mRunCondition->unlock(); +} + + +//============================================================================ + +// see llmemory.h for LLPointer<> definition + +class LL_COMMON_API LLThreadSafeRefCount +{ +public: +	static void initThreadSafeRefCount(); // creates sMutex +	static void cleanupThreadSafeRefCount(); // destroys sMutex +	 +private: +	static LLMutex* sMutex; + +private: +	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented +	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented + +protected: +	virtual ~LLThreadSafeRefCount(); // use unref() +	 +public: +	LLThreadSafeRefCount(); +	 +	void ref() +	{ +		if (sMutex) sMutex->lock(); +		mRef++;  +		if (sMutex) sMutex->unlock(); +	}  + +	S32 unref() +	{ +		llassert(mRef >= 1); +		if (sMutex) sMutex->lock(); +		S32 res = --mRef; +		if (sMutex) sMutex->unlock(); +		if (0 == res)  +		{ +			delete this;  +			return 0; +		} +		return res; +	}	 +	S32 getNumRefs() const +	{ +		return mRef; +	} + +private:  +	S32	mRef;  +}; + +//============================================================================ + +// Simple responder for self destructing callbacks +// Pure virtual class +class LL_COMMON_API LLResponder : public LLThreadSafeRefCount +{ +protected: +	virtual ~LLResponder(); +public: +	virtual void completed(bool success) = 0; +}; + +//============================================================================ + +#endif // LL_LLTHREAD_H | 
