PageRenderTime 30ms CodeModel.GetById 15ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llcommon/llthread.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 283 lines | 170 code | 58 blank | 55 comment | 16 complexity | 8e083e735df34af28bdc9e29341c1a10 MD5 | raw file
  1/** 
  2 * @file llthread.h
  3 * @brief Base classes for thread, mutex and condition handling.
  4 *
  5 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLTHREAD_H
 28#define LL_LLTHREAD_H
 29
 30#include "llapp.h"
 31#include "llapr.h"
 32#include "apr_thread_cond.h"
 33
 34class LLThread;
 35class LLMutex;
 36class LLCondition;
 37
 38#if LL_WINDOWS
 39#define ll_thread_local __declspec(thread)
 40#else
 41#define ll_thread_local __thread
 42#endif
 43
 44class LL_COMMON_API LLThread
 45{
 46private:
 47	static U32 sIDIter;
 48
 49public:
 50	typedef enum e_thread_status
 51	{
 52		STOPPED = 0,	// The thread is not running.  Not started, or has exited its run function
 53		RUNNING = 1,	// The thread is currently running
 54		QUITTING= 2 	// Someone wants this thread to quit
 55	} EThreadStatus;
 56
 57	LLThread(const std::string& name, apr_pool_t *poolp = NULL);
 58	virtual ~LLThread(); // Warning!  You almost NEVER want to destroy a thread unless it's in the STOPPED state.
 59	virtual void shutdown(); // stops the thread
 60	
 61	bool isQuitting() const { return (QUITTING == mStatus); }
 62	bool isStopped() const { return (STOPPED == mStatus); }
 63	
 64	static U32 currentID(); // Return ID of current thread
 65	static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
 66	
 67public:
 68	// PAUSE / RESUME functionality. See source code for important usage notes.
 69	// Called from MAIN THREAD.
 70	void pause();
 71	void unpause();
 72	bool isPaused() { return isStopped() || mPaused == TRUE; }
 73	
 74	// Cause the thread to wake up and check its condition
 75	void wake();
 76
 77	// Same as above, but to be used when the condition is already locked.
 78	void wakeLocked();
 79
 80	// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
 81	void checkPause();
 82
 83	// this kicks off the apr thread
 84	void start(void);
 85
 86	apr_pool_t *getAPRPool() { return mAPRPoolp; }
 87	LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
 88
 89	U32 getID() const { return mID; }
 90
 91private:
 92	BOOL				mPaused;
 93	
 94	// static function passed to APR thread creation routine
 95	static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
 96
 97protected:
 98	std::string			mName;
 99	LLCondition*		mRunCondition;
100
101	apr_thread_t		*mAPRThreadp;
102	apr_pool_t			*mAPRPoolp;
103	BOOL				mIsLocalPool;
104	EThreadStatus		mStatus;
105	U32					mID;
106
107	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
108	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
109	//      otherwise it will cause severe memory leaking!!! --bao
110	LLVolatileAPRPool  *mLocalAPRFilePoolp ; 
111
112	void setQuitting();
113	
114	// virtual function overridden by subclass -- this will be called when the thread runs
115	virtual void run(void) = 0; 
116	
117	// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
118	virtual bool runCondition(void);
119
120	// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
121	inline void lockData();
122	inline void unlockData();
123	
124	// This is the predicate that decides whether the thread should sleep.  
125	// It should only be called with mRunCondition locked, since the virtual runCondition() function may need to access
126	// data structures that are thread-unsafe.
127	bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
128
129	// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
130	// mRunCondition->lock();
131	// if(!shouldSleep())
132	//     mRunCondition->signal();
133	// mRunCondition->unlock();
134};
135
136//============================================================================
137
138#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
139
140class LL_COMMON_API LLMutex
141{
142public:
143	typedef enum
144	{
145		NO_THREAD = 0xFFFFFFFF
146	} e_locking_thread;
147
148	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
149	virtual ~LLMutex();
150	
151	void lock();		// blocks
152	void unlock();
153	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
154	bool isSelfLocked(); //return true if locked in a same thread
155	U32 lockingThread() const; //get ID of locking thread
156	
157protected:
158	apr_thread_mutex_t *mAPRMutexp;
159	mutable U32			mCount;
160	mutable U32			mLockingThread;
161	
162	apr_pool_t			*mAPRPoolp;
163	BOOL				mIsLocalPool;
164	
165#if MUTEX_DEBUG
166	std::map<U32, BOOL> mIsLocked;
167#endif
168};
169
170// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
171class LL_COMMON_API LLCondition : public LLMutex
172{
173public:
174	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
175	~LLCondition();
176	
177	void wait();		// blocks
178	void signal();
179	void broadcast();
180	
181protected:
182	apr_thread_cond_t *mAPRCondp;
183};
184
185class LLMutexLock
186{
187public:
188	LLMutexLock(LLMutex* mutex)
189	{
190		mMutex = mutex;
191		
192		if(mMutex)
193			mMutex->lock();
194	}
195	~LLMutexLock()
196	{
197		if(mMutex)
198			mMutex->unlock();
199	}
200private:
201	LLMutex* mMutex;
202};
203
204//============================================================================
205
206void LLThread::lockData()
207{
208	mRunCondition->lock();
209}
210
211void LLThread::unlockData()
212{
213	mRunCondition->unlock();
214}
215
216
217//============================================================================
218
219// see llmemory.h for LLPointer<> definition
220
221class LL_COMMON_API LLThreadSafeRefCount
222{
223public:
224	static void initThreadSafeRefCount(); // creates sMutex
225	static void cleanupThreadSafeRefCount(); // destroys sMutex
226	
227private:
228	static LLMutex* sMutex;
229
230private:
231	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
232	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
233
234protected:
235	virtual ~LLThreadSafeRefCount(); // use unref()
236	
237public:
238	LLThreadSafeRefCount();
239	
240	void ref()
241	{
242		if (sMutex) sMutex->lock();
243		mRef++; 
244		if (sMutex) sMutex->unlock();
245	} 
246
247	S32 unref()
248	{
249		llassert(mRef >= 1);
250		if (sMutex) sMutex->lock();
251		S32 res = --mRef;
252		if (sMutex) sMutex->unlock();
253		if (0 == res) 
254		{
255			delete this; 
256			return 0;
257		}
258		return res;
259	}	
260	S32 getNumRefs() const
261	{
262		return mRef;
263	}
264
265private: 
266	S32	mRef; 
267};
268
269//============================================================================
270
271// Simple responder for self destructing callbacks
272// Pure virtual class
273class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
274{
275protected:
276	virtual ~LLResponder();
277public:
278	virtual void completed(bool success) = 0;
279};
280
281//============================================================================
282
283#endif // LL_LLTHREAD_H