1
2
3 #include "tthread.h"
4 #define _WIN32_WINNT 0x0400
5 #include <windows.h>
6
7 class TThreadGroupImp;
8 //---------------------------------------------------------------------------
9 // TMutex & TMutexImp
10 //---------------------------------------------------------------------------
11
12 class TMutexImp {
13 HANDLE id;
14
15 public:
16 TMutexImp();
17 ~TMutexImp();
18 void lock();
19 void unlock();
20 };
21
22 //---------------------------------------------------------------------------
23
24 class TThreadGroupImp {
25 std::list<TThread *> threads;
26
27 public:
28 TThreadGroupImp();
29 ~TThreadGroupImp();
30 void add(TThread *);
31 void remove(TThread *);
32 void wait();
33 };
34 //---------------------------------------------------------------------------
35
TMutexImp()36 TMutexImp::TMutexImp() { id = CreateMutex(NULL, FALSE, NULL); }
37
38 //---------------------------------------------------------------------------
39
~TMutexImp()40 TMutexImp::~TMutexImp() { BOOL rc = CloseHandle(id); }
41 //---------------------------------------------------------------------------
42
lock()43 void TMutexImp::lock() { DWORD rc = WaitForSingleObject(id, INFINITE); }
44
45 //---------------------------------------------------------------------------
46
unlock()47 void TMutexImp::unlock() { BOOL rc = ReleaseMutex(id); }
48
49 //---------------------------------------------------------------------------
50
TMutex()51 TMutex::TMutex() : m_imp(new TMutexImp()) {}
52
53 //---------------------------------------------------------------------------
54
~TMutex()55 TMutex::~TMutex() { delete m_imp; }
56 //---------------------------------------------------------------------------
57
lock()58 void TMutex::lock() { m_imp->lock(); }
59
60 //---------------------------------------------------------------------------
61
unlock()62 void TMutex::unlock() { m_imp->unlock(); }
63
64 //---------------------------------------------------------------------------
65 //---------------------------------------------------------------------------
66 // TThread & TThreadImp
67 //---------------------------------------------------------------------------
68
69 class TThreadImp {
70 public:
71 friend class TThreadGroupImp;
72
73 HANDLE threadId;
74 HANDLE mainThread;
75 int m_refCount;
76 TMutex secureLock;
77 bool isRunning;
78 TThreadGroupImp *owner;
79 TThread *thread;
80
81 // some static stuff
82 static TUINT32 nThreads;
83 static TMutex mutex;
84
85 TThreadImp();
86 ~TThreadImp();
87
88 void start();
89
90 bool setThreadPriority(TThread::TThreadPriority p);
91 bool setPreferredProcessor(int processorId);
92
incNThreads()93 static void incNThreads() {
94 mutex.lock();
95 nThreads++;
96 mutex.unlock();
97 }
decNThreads()98 static void decNThreads() {
99 mutex.lock();
100 nThreads--;
101 mutex.unlock();
102 }
103
setOwner(TThreadGroupImp * _owner)104 void setOwner(TThreadGroupImp *_owner) { owner = _owner; }
105 };
106
107 TUINT32 TThreadImp::nThreads = 0;
108 TMutex TThreadImp::mutex = TMutex();
109
110 //---------------------------------------------------------------------------
111
TThreadImp()112 TThreadImp::TThreadImp()
113 : isRunning(false)
114 , threadId(0)
115 , owner(0)
116 , mainThread(0)
117 , thread(0)
118 , secureLock()
119 , m_refCount(0) {}
120
121 //---------------------------------------------------------------------------
122
~TThreadImp()123 TThreadImp::~TThreadImp() {
124 if (threadId) CloseHandle(threadId);
125 }
126
127 //---------------------------------------------------------------------------
128
fun(void * data)129 static TUINT32 __stdcall fun(void *data) {
130 TThreadImp *t = (TThreadImp *)data;
131
132 t->secureLock.lock();
133 if (t->isRunning) {
134 t->secureLock.unlock();
135 assert(!"thread is already running");
136 return 0;
137 }
138 t->isRunning = true;
139
140 t->secureLock.unlock();
141
142 t->thread->run();
143
144 t->decNThreads();
145 if (t->owner) t->owner->remove(t->thread);
146 t->thread->release();
147 return 0;
148 }
149
150 //---------------------------------------------------------------------------
151
start()152 void TThreadImp::start() {
153 TThreadImp::incNThreads();
154 threadId = CreateThread(0, 0, fun, this, 0, 0);
155 }
156 //---------------------------------------------------------------------------
157
setThreadPriority(TThread::TThreadPriority p)158 bool TThreadImp::setThreadPriority(TThread::TThreadPriority p) {
159 int priority;
160 switch (p) {
161 case TThread::TIME_CRITICAL:
162 priority = THREAD_PRIORITY_TIME_CRITICAL;
163 break;
164 case TThread::HIGHEST:
165 priority = THREAD_PRIORITY_HIGHEST;
166 break;
167 case TThread::ABOVE_NORMAL:
168 priority = THREAD_PRIORITY_ABOVE_NORMAL;
169 break;
170 case TThread::NORMAL:
171 priority = THREAD_PRIORITY_NORMAL;
172 break;
173 case TThread::BELOW_NORMAL:
174 priority = THREAD_PRIORITY_BELOW_NORMAL;
175 break;
176 case TThread::LOWEST:
177 priority = THREAD_PRIORITY_LOWEST;
178 break;
179 case TThread::IDLE:
180 priority = THREAD_PRIORITY_IDLE;
181 break;
182 default:
183 priority = THREAD_PRIORITY_NORMAL;
184 break;
185 }
186 return !!SetThreadPriority(threadId, priority);
187 }
188
189 //---------------------------------------------------------------------------
190
setPreferredProcessor(int processorId)191 bool TThreadImp::setPreferredProcessor(int processorId) {
192 DWORD rc = SetThreadIdealProcessor(threadId, processorId);
193 return (rc != -1);
194 }
195
196 //---------------------------------------------------------------------------
197
TThread()198 TThread::TThread() : m_imp(new TThreadImp()) { m_imp->thread = this; }
199
200 //---------------------------------------------------------------------------
201
~TThread()202 TThread::~TThread() { delete m_imp; }
203
204 //---------------------------------------------------------------------------
205
start()206 void TThread::start() {
207 addRef();
208 m_imp->start();
209 }
210
211 //---------------------------------------------------------------------------
212
addRef()213 void TThread::addRef() {
214 m_imp->mutex.lock();
215 m_imp->m_refCount++;
216 m_imp->mutex.unlock();
217 }
218
219 //---------------------------------------------------------------------------
220
release()221 void TThread::release() {
222 bool kill = false;
223 m_imp->mutex.lock();
224 m_imp->m_refCount--;
225 if (m_imp->m_refCount <= 0) kill = true;
226 m_imp->mutex.unlock();
227 if (kill) delete this;
228 }
229
230 //---------------------------------------------------------------------------
231
getRefCount()232 int TThread::getRefCount() { return m_imp->m_refCount; }
233
234 //---------------------------------------------------------------------------
235
setPreferredProcessor(int processorId)236 bool TThread::setPreferredProcessor(int processorId) {
237 return m_imp->setPreferredProcessor(processorId);
238 }
239
240 //---------------------------------------------------------------------------
241
setThreadPriority(TThread::TThreadPriority p)242 bool TThread::setThreadPriority(TThread::TThreadPriority p) {
243 return m_imp->setThreadPriority(p);
244 }
245
246 //=======================
247 // TThreadGroupImp
248
249 //---------------------------------------------------------------------------
250
TThreadGroupImp()251 TThreadGroupImp::TThreadGroupImp() {}
252
253 //---------------------------------------------------------------------------
254
~TThreadGroupImp()255 TThreadGroupImp::~TThreadGroupImp() {}
256
257 //---------------------------------------------------------------------------
add(TThread * t)258 void TThreadGroupImp::add(TThread *t) {
259 threads.push_back(t);
260 t->m_imp->setOwner(this);
261 }
262 //---------------------------------------------------------------------------
263
remove(TThread * t)264 void TThreadGroupImp::remove(TThread *t) {
265 threads.remove(t);
266 t->m_imp->setOwner(0);
267 }
268 //---------------------------------------------------------------------------
269
wait()270 void TThreadGroupImp::wait() {
271 DWORD count = threads.size();
272 if (count == 0) return;
273 HANDLE *hThreads = new HANDLE[count];
274 int id = 0;
275 for (std::list<TThread *>::iterator it = threads.begin(); it != threads.end();
276 it++, id++) {
277 TThread *t = *it;
278 if (t->m_imp->threadId == 0) t->start();
279 hThreads[id] = t->m_imp->threadId;
280 }
281
282 DWORD rc = WaitForMultipleObjects(count, hThreads, FALSE, INFINITE);
283 if (rc >= WAIT_OBJECT_0 && rc <= (WAIT_OBJECT_0 + count - 1)) {
284 // cout << "obj #" << rc << endl;
285 }
286 if (rc >= WAIT_ABANDONED_0 && rc <= (WAIT_ABANDONED_0 + count - 1)) {
287 // cout << "obj #" << rc << " abandoned" << endl;
288 }
289 if (rc == WAIT_TIMEOUT) {
290 // cout << "timeout" << endl;
291 }
292
293 if (rc == WAIT_FAILED) {
294 // cout << "failed" << endl;
295 }
296
297 delete[] hThreads;
298 wait();
299 }
300
301 //---------------------------------------------------------------------------
302
TThreadGroup()303 TThreadGroup::TThreadGroup()
304 : m_imp(new TThreadGroupImp())
305
306 {}
307
308 //---------------------------------------------------------------------------
309
~TThreadGroup()310 TThreadGroup::~TThreadGroup() { delete m_imp; }
311
312 //---------------------------------------------------------------------------
313
add(TThread * t)314 void TThreadGroup::add(TThread *t) { m_imp->add(t); }
315
316 //---------------------------------------------------------------------------
317
wait()318 void TThreadGroup::wait() { m_imp->wait(); }
319