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
|
/**
* @file llworkerthread.h
*
* Copyright (c) 2004-$CurrentYear$, Linden Research, Inc.
* $License$
*/
#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
|