1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
/**
* @file llworkerthread.h
*
* Copyright (c) 2004-2007, Linden Research, Inc.
*
* 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://secondlife.com/developers/opensource/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://secondlife.com/developers/opensource/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.
*/
#ifndef LL_LLWORKERTHREAD_H
#define LL_LLWORKERTHREAD_H
#include <queue>
#include <string>
#include <map>
#include <set>
#include "llqueuedthread.h"
#define USE_FRAME_CALLBACK_MANAGER 0
//============================================================================
class LLWorkerClass;
//============================================================================
// Note: ~LLWorkerThread is O(N) N=# of worker threads, assumed to be small
// It is assumed that LLWorkerThreads are rarely created/destroyed.
class LLWorkerThread : public LLQueuedThread
{
public:
class Request : public LLQueuedThread::QueuedRequest
{
protected:
~Request() {}; // use deleteRequest()
public:
Request(handle_t handle, U32 priority, LLWorkerClass* workerclass, S32 param);
S32 getParam()
{
return mParam;
}
LLWorkerClass* getWorkerClass()
{
return mWorkerClass;
}
/*virtual*/ void deleteRequest();
private:
LLWorkerClass* mWorkerClass;
S32 mParam;
};
public:
LLWorkerThread(bool threaded = true, bool runalways = true);
~LLWorkerThread();
protected:
/*virtual*/ bool processRequest(QueuedRequest* req);
public:
handle_t add(LLWorkerClass* workerclass, S32 param, U32 priority = PRIORITY_NORMAL);
static void initClass(bool local_is_threaded = true, bool local_run_always = true); // Setup sLocal
static S32 updateClass(U32 ms_elapsed);
static S32 getAllPending();
static void pauseAll();
static void waitOnAllPending();
static void cleanupClass(); // Delete sLocal
public:
static LLWorkerThread* sLocal; // Default worker thread
static std::set<LLWorkerThread*> sThreadList; // array of threads (includes sLocal)
};
//============================================================================
// This is a base class which any class with worker functions should derive from.
// Example Usage:
// LLMyWorkerClass* foo = new LLMyWorkerClass();
// foo->fetchData(); // calls addWork()
// while(1) // main loop
// {
// if (foo->hasData()) // calls checkWork()
// foo->processData();
// }
//
// WorkerClasses only have one set of work functions. If they need to do multiple
// background tasks, use 'param' to switch amnong them.
// Only one background task can be active at a time (per instance).
// i.e. don't call addWork() if haveWork() returns true
class LLWorkerClass
{
public:
typedef LLWorkerThread::handle_t handle_t;
enum FLAGS
{
WCF_WORKING = 0x01,
WCF_ABORT_REQUESTED = 0x80
};
public:
LLWorkerClass(LLWorkerThread* workerthread, const std::string& name);
virtual ~LLWorkerClass();
// pure virtual, called from WORKER THREAD, returns TRUE if done
virtual bool doWork(S32 param)=0; // Called from LLWorkerThread::processRequest()
// called from WORKER THREAD
void setWorking(bool working) { working ? setFlags(WCF_WORKING) : clearFlags(WCF_WORKING); }
bool isWorking() { return getFlags(WCF_WORKING); }
bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
const std::string& getName() const { return mWorkerClassName; }
protected:
// Call from doWork only to avoid eating up cpu time.
// Returns true if work has been aborted
// yields the current thread and calls mWorkerThread->checkPause()
bool yield();
void setWorkerThread(LLWorkerThread* workerthread);
// addWork(): calls startWork, adds doWork() to queue
void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL);
// abortWork(): requests that work be aborted
void abortWork();
// checkWork(): if doWork is complete or aborted, call endWork() and return true
bool checkWork();
// haveWork(): return true if mWorkHandle != null
bool haveWork() { return mWorkHandle != LLWorkerThread::nullHandle(); }
// killWork(): aborts work and waits for the abort to process
void killWork();
// setPriority(): changes the priority of a request
void setPriority(U32 priority);
private:
void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; }
void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; }
U32 getFlags() { return mWorkFlags; }
bool getFlags(U32 flags) { return mWorkFlags & flags ? true : false; }
private:
// pure virtuals
virtual void startWork(S32 param)=0; // called from addWork() (MAIN THREAD)
virtual void endWork(S32 param, bool aborted)=0; // called from doWork() (MAIN THREAD)
protected:
LLWorkerThread* mWorkerThread;
std::string mWorkerClassName;
handle_t mWorkHandle;
private:
LLAtomicU32 mWorkFlags;
};
//============================================================================
#endif // LL_LLWORKERTHREAD_H
|