PageRenderTime 28ms CodeModel.GetById 18ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llcommon/llqueuedthread.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 213 lines | 140 code | 35 blank | 38 comment | 2 complexity | f652f978bc1c8c6e1955eeaee9193215 MD5 | raw file
  1/** 
  2 * @file llqueuedthread.h
  3 * @brief
  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_LLQUEUEDTHREAD_H
 28#define LL_LLQUEUEDTHREAD_H
 29
 30#include <queue>
 31#include <string>
 32#include <map>
 33#include <set>
 34
 35#include "llapr.h"
 36
 37#include "llthread.h"
 38#include "llsimplehash.h"
 39
 40//============================================================================
 41// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
 42//   It is assumed that LLQueuedThreads are rarely created/destroyed.
 43
 44class LL_COMMON_API LLQueuedThread : public LLThread
 45{
 46	//------------------------------------------------------------------------
 47public:
 48	enum priority_t {
 49		PRIORITY_IMMEDIATE = 0x7FFFFFFF,
 50		PRIORITY_URGENT =    0x40000000,
 51		PRIORITY_HIGH =      0x30000000,
 52		PRIORITY_NORMAL =    0x20000000,
 53		PRIORITY_LOW =       0x10000000,
 54		PRIORITY_LOWBITS =   0x0FFFFFFF,
 55		PRIORITY_HIGHBITS =  0x70000000
 56	};
 57	enum status_t {
 58		STATUS_EXPIRED = -1,
 59		STATUS_UNKNOWN = 0,
 60		STATUS_QUEUED = 1,
 61		STATUS_INPROGRESS = 2,
 62		STATUS_COMPLETE = 3,
 63		STATUS_ABORTED = 4,
 64		STATUS_DELETE = 5
 65	};
 66	enum flags_t {
 67		FLAG_AUTO_COMPLETE = 1,
 68		FLAG_AUTO_DELETE = 2, // child-class dependent
 69		FLAG_ABORT = 4
 70	};
 71
 72	typedef U32 handle_t;
 73	
 74	//------------------------------------------------------------------------
 75public:
 76
 77	class LL_COMMON_API QueuedRequest : public LLSimpleHashEntry<handle_t>
 78	{
 79		friend class LLQueuedThread;
 80		
 81	protected:
 82		virtual ~QueuedRequest(); // use deleteRequest()
 83		
 84	public:
 85		QueuedRequest(handle_t handle, U32 priority, U32 flags = 0);
 86
 87		status_t getStatus()
 88		{
 89			return mStatus;
 90		}
 91		U32 getPriority() const
 92		{
 93			return mPriority;
 94		}
 95		U32 getFlags() const
 96		{
 97			return mFlags;
 98		}
 99		bool higherPriority(const QueuedRequest& second) const
100		{
101			if ( mPriority == second.mPriority)
102				return mHashKey < second.mHashKey;
103			else
104				return mPriority > second.mPriority;
105		}
106
107	protected:
108		status_t setStatus(status_t newstatus)
109		{
110			status_t oldstatus = mStatus;
111			mStatus = newstatus;
112			return oldstatus;
113		}
114		void setFlags(U32 flags)
115		{
116			// NOTE: flags are |'d
117			mFlags |= flags;
118		}
119		
120		virtual bool processRequest() = 0; // Return true when request has completed
121		virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
122		virtual void deleteRequest(); // Only method to delete a request
123
124		void setPriority(U32 pri)
125		{
126			// Only do this on a request that is not in a queued list!
127			mPriority = pri;
128		};
129		
130	protected:
131		LLAtomic32<status_t> mStatus;
132		U32 mPriority;
133		U32 mFlags;
134	};
135
136protected:
137	struct queued_request_less
138	{
139		bool operator()(const QueuedRequest* lhs, const QueuedRequest* rhs) const
140		{
141			return lhs->higherPriority(*rhs); // higher priority in front of queue (set)
142		}
143	};
144
145
146	//------------------------------------------------------------------------
147	
148public:
149	static handle_t nullHandle() { return handle_t(0); }
150	
151public:
152	LLQueuedThread(const std::string& name, bool threaded = true, bool should_pause = false);
153	virtual ~LLQueuedThread();	
154	virtual void shutdown();
155	
156private:
157	// No copy constructor or copy assignment
158	LLQueuedThread(const LLQueuedThread&);
159	LLQueuedThread& operator=(const LLQueuedThread&);
160
161	virtual bool runCondition(void);
162	virtual void run(void);
163	virtual void startThread(void);
164	virtual void endThread(void);
165	virtual void threadedUpdate(void);
166
167protected:
168	handle_t generateHandle();
169	bool addRequest(QueuedRequest* req);
170	S32  processNextRequest(void);
171	void incQueue();
172
173public:
174	bool waitForResult(handle_t handle, bool auto_complete = true);
175
176	virtual S32 update(F32 max_time_ms);
177	S32 updateQueue(F32 max_time_ms);
178	
179	void waitOnPending();
180	void printQueueStats();
181
182	virtual S32 getPending();
183	bool getThreaded() { return mThreaded ? true : false; }
184
185	// Request accessors
186	status_t getRequestStatus(handle_t handle);
187	void abortRequest(handle_t handle, bool autocomplete);
188	void setFlags(handle_t handle, U32 flags);
189	void setPriority(handle_t handle, U32 priority);
190	bool completeRequest(handle_t handle);
191	// This is public for support classes like LLWorkerThread,
192	// but generally the methods above should be used.
193	QueuedRequest* getRequest(handle_t handle);
194
195	// debug (see source)
196	bool check();
197	
198protected:
199	BOOL mThreaded;  // if false, run on main thread and do updates during update()
200	BOOL mStarted;  // required when mThreaded is false to call startThread() from update()
201	LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
202	
203	typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
204	request_queue_t mRequestQueue;
205
206	enum { REQUEST_HASH_SIZE = 512 }; // must be power of 2
207	typedef LLSimpleHash<handle_t, REQUEST_HASH_SIZE> request_hash_t;
208	request_hash_t mRequestHash;
209
210	handle_t mNextHandle;
211};
212
213#endif // LL_LLQUEUEDTHREAD_H