ETL  0.04.19
_thread.h
Go to the documentation of this file.
1 
25 /* === S T A R T =========================================================== */
26 
27 #ifndef __ETL__THREAD_H_
28 #define __ETL__THREAD_H_
29 
30 /* === H E A D E R S ======================================================= */
31 
32 #define __USE_GNU
33 
34 #ifdef HAVE_PTHREAD_H
35 # include <pthread.h>
36 #endif
37 
38 #ifdef HAVE_SCHED_H
39 # include <sched.h>
40 #endif
41 
42 #ifdef HAVE_CREATETHREAD
43 # include <windows.h>
44 #endif
45 
46 /* === M A C R O S ========================================================= */
47 
48 #if ( defined (HAVE_PTHREAD_CREATE) || defined (HAVE_CLONE) || defined (HAVE_CREATETHREAD) ) && !defined (NO_THREADS)
49 # define CALLISTO_THREADS
50 #endif
51 
52 #define THREAD_ENTRYPOINT
53 
54 /* === C L A S S E S & S T R U C T S ======================================= */
55 
56 #if defined(CALLISTO_THREADS) && defined(HAVE_PTHREAD_CREATE)
57 static inline void Yield(void)
58 {
59  sched_yield();
60  pthread_testcancel();
61 }
62 #else
63 #ifdef Yield
64  #undef Yield
65 #endif
66 inline void Yield(void) { }
67 #endif
68 
69 #ifdef CALLISTO_THREADS
70 
71 #ifdef HAVE_PTHREAD_CREATE
72 
73 class Thread
74 {
75 public:
76  typedef void* entrypoint_return;
77 private:
78 
79  pthread_t thread;
80  int *references;
81  entrypoint_return (*entrypoint)(void *);
82  void *context;
83 public:
84  Thread(void *(*ep)(void *)=NULL,void *context=NULL):
85  references(NULL),entrypoint(ep),context(context) { }
86  Thread(const Thread &t)
87  {
88  thread=t.thread;
89  references=t.references;
90  entrypoint=t.entrypoint;
91  context=t.context;
92  if(references)
93  (*references)++;
94  }
95  const Thread &operator=(const Thread &rhs)
96  {
97  if(references)
98  {
99  (*references)--;
100  if(*references==0)
101  stop();
102  }
103  thread=rhs.thread;
104  references=rhs.references;
105  entrypoint=rhs.entrypoint;
106  context=rhs.context;
107  if(references)
108  (*references)++;
109  return *this;
110  }
111 
112  void start(void)
113  {
114  references = new int;
115  *references = 1;
116  pthread_create(&thread,NULL,entrypoint,context);
117 // pthread_detach(thread);
118  }
119 
120  void stop(void)
121  {
122  delete references;
123  references=NULL;
124  void *exit_status;
125  pthread_cancel(thread);
126  pthread_join(thread,&exit_status);
127  }
128 
129  static void TestStop()
130  {
131  pthread_testcancel();
132  }
133 
134  static void SyncStop()
135  {
136  int i;
137  pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,&i);
138  }
139 
140  static void AsyncStop()
141  {
142  int i;
143  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&i);
144  }
145 
146  ~Thread()
147  {
148  if(references)
149  {
150  (*references)--;
151  if(*references==0)
152  stop();
153  }
154  }
155 };
156 
157 class Mutex
158 {
159  pthread_mutex_t mutex;
160  pthread_t locker;
161  int depth;
162 public:
163 
164  Mutex()
165  {
166  pthread_mutexattr_t attr;
167  pthread_mutexattr_init(&attr);
168  //#ifdef PTHREAD_PRIO_INHERIT
169  //pthread_mutexattr_setprioceiling(&attr,PTHREAD_PRIO_INHERIT);
170  //#endif
171  #ifdef PTHREAD_MUTEX_RECURSIVE
172  pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
173  #endif
174  pthread_mutex_init(&mutex,&attr);
175  pthread_mutexattr_destroy(&attr);
176  locker=0;
177  depth=0;
178  }
179 
180  ~Mutex()
181  { pthread_mutex_destroy(&mutex); }
182 
183  void Lock(void)
184  {
185  if(!locker || locker!=pthread_self())
186  {
187  pthread_mutex_lock(&mutex);
188  locker=pthread_self();
189  depth=0;
190  return;
191  }
192  depth++;
193  }
194 
195  bool TryLock(void)
196  { return !(bool) pthread_mutex_trylock(&mutex); }
197 
198  void UnLock(void)
199  {
200  if(depth)
201  {
202  depth--;
203  return;
204  }
205  pthread_mutex_unlock(&mutex);
206  locker=0;
207  }
208 };
209 
210 #ifdef HAVE_PTHREAD_RW_LOCK_INIT
211 class ReadWriteLock
212 {
213  pthread_rwlock_t rwlock;
214 public:
215 
216  ReadWriteLock()
217  { pthread_rwlock_init(&rwlock,NULL); }
218 
220  { pthread_rwlock_destroy(&rwlock); }
221 
222  void LockRead(void)
223  { pthread_rwlock_rdlock(&rwlock); }
224 
225  void LockWrite(void)
226  { pthread_rwlock_wrlock(&rwlock); }
227 
228  bool TryLockRead(void)
229  { return !(bool)pthread_rwlock_tryrdlock(&rwlock); }
230 
231  bool TryLockWrite(void)
232  { return !(bool)pthread_rwlock_trywrlock(&rwlock); }
233 
234  void UnLockWrite(void)
235  { pthread_rwlock_unlock(&rwlock); }
236 
237  void UnLockRead(void)
238  { pthread_rwlock_unlock(&rwlock); }
239 };
240 #else
241 //*
242 class ReadWriteLock : public Mutex
243 {
244 public:
245 
246  ReadWriteLock()
247  { }
248 
250  { }
251 
252  void LockRead(void)
253  { Lock(); }
254 
255  void LockWrite(void)
256  { Lock(); }
257 
258  bool TryLockRead(void)
259  { return TryLock(); }
260 
261  bool TryLockWrite(void)
262  { return TryLock(); }
263 
264  void UnLockWrite(void)
265  { UnLock(); }
266 
267  void UnLockRead(void)
268  { UnLock(); }
269 };
270 #endif
271 
272 /*
273 class Condition
274 {
275  pthread_cond_t cond;
276  pthread_mutex_t mutex;
277 public:
278  Condition()
279  { pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,NULL); }
280  ~Condition()
281  { pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex);}
282  void operator()(void)
283  { pthread_cond_signal(&cond); }
284  void Wait(void)
285  {
286  pthread_mutex_lock(&mutex);
287  pthread_cond_wait(&cond,&mutex);
288  pthread_mutex_unlock(&mutex);
289  }
290 };
291 */
292 
293 #else // if defined HAVE_PTHREAD
294 #ifdef HAVE_CREATETHREAD
295 
296 
297 #ifdef THREAD_ENTRYPOINT
298 #undef THREAD_ENTRYPOINT
299 #endif
300 #define THREAD_ENTRYPOINT __stdcall
301 class Thread
302 {
303 public:
304  typedef unsigned long entrypoint_return;
305 private:
306 
307  unsigned long thread;
308  HANDLE handle;
309  int *references;
310 
311  entrypoint_return (THREAD_ENTRYPOINT *entrypoint)(void *);
312 
313  void *context;
314 
315  HDC hdc;
316  HGLRC hglrc;
317 
318  static entrypoint_return THREAD_ENTRYPOINT thread_prefix(void*data)
319  {
320  Thread *thread=(Thread *)data;
321 
322  if(thread->hglrc)
323  wglMakeCurrent(thread->hdc, thread->hglrc);
324 
325  return thread->entrypoint(thread->context);
326  }
327 
328 public:
329  Thread(entrypoint_return (THREAD_ENTRYPOINT *ep)(void *)=NULL,void *context=NULL):
330  references(NULL),entrypoint(ep),context(context) { }
331  Thread(const Thread &t)
332  {
333  thread=t.thread;
334  handle=t.handle;
335  references=t.references;
336  entrypoint=t.entrypoint;
337  context=t.context;
338  handle=NULL;
339  if(references)
340  (*references)++;
341  }
342  const Thread &operator=(const Thread &rhs)
343  {
344  if(references)
345  {
346  (*references)--;
347  if(*references==0)
348  stop();
349  }
350  thread=rhs.thread;
351  handle=rhs.handle;
352  references=rhs.references;
353  entrypoint=rhs.entrypoint;
354  context=rhs.context;
355  if(references)
356  (*references)++;
357  return *this;
358  }
359 
360  void start(void)
361  {
362  references = new int;
363  *references = 1;
364 
365  hglrc=wglGetCurrentContext();
366  hdc=wglGetCurrentDC();
367 
368  handle=CreateThread(
369  NULL, // Security stuff
370  0, // STACK
371  thread_prefix, // thread function
372  (void*)this, // thread argument
373  0, // creation option
374  &thread // thread identifier
375  );
376  }
377 
378  void stop(void)
379  {
380  delete references;
381  references=NULL;
382 
383  TerminateThread(handle, FALSE);
384  }
385 
386  int wait(void)
387  {
388  if(handle)
389  {
390  WaitForSingleObject(handle, INFINITE);
391  CloseHandle(handle);
392  }
393  return 0;
394  }
395 
396  static void TestStop()
397  {
398  }
399 
400  static void SyncStop()
401  {
402  }
403 
404  static void AsyncStop()
405  {
406  }
407 
408  ~Thread()
409  {
410  if(references)
411  {
412  (*references)--;
413  if(*references==0)
414  stop();
415  }
416  }
417 };
418 
419 class Mutex
420 {
421  HANDLE handle;
422 public:
423 
424  Mutex()
425  {
426  handle = CreateMutex(NULL, FALSE, NULL);
427  }
428 
429  ~Mutex()
430  {
431  CloseHandle(handle);
432  }
433 
434  void Lock(void)
435  {
436  WaitForSingleObject(handle, INFINITE);
437  }
438 
439  bool TryLock(void)
440  {
441  return WaitForSingleObject(handle, INFINITE)==WAIT_FAILED;
442  }
443 
444  void UnLock(void)
445  {
446  ReleaseMutex(handle);
447  }
448 };
449 
450 
451 #endif // if defined HAVE_CREATETHREAD
452 #endif // if defined HAVE_PTHREAD_CREATE
453 #endif // if defined CALLISTO_THREADS
454 
455 
456 #if !defined(CALLISTO_THREADS)
457 // Dummy object used when not threading
459 {
460 public:
461 
464  void LockRead(void) {}
465  void LockWrite(void) {}
466  bool TryLockRead(void) {return true;}
467  bool TryLockWrite(void) {return true;}
468  void UnLockRead(void) {}
469  void UnLockWrite(void) {}
470 };
471 
472 class Mutex
473 {
474 public:
475 
476  Mutex(){}
477  ~Mutex(){}
478  void Lock(void){}
479  bool TryLock(void){return true;}
480  void UnLock(void){}
481 };
482 
483 #endif
484 
485 class Condition : private Mutex
486 {
487  bool flag;
488 public:
490  { flag=false; }
492  { }
493  void operator()(void)
494  { flag=true; }
495  void Wait(void)
496  {
497  Lock();
498  while(!flag)Yield();
499  flag=false;
500  UnLock();
501  }
502  void WaitNext(void)
503  {
504  Lock();
505  flag=false;
506  while(!flag)Yield();
507  UnLock();
508  }
509 };
510 
511 /* === E X T E R N S ======================================================= */
512 
513 /* === E N D =============================================================== */
514 
515 #endif