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