1 /*! ========================================================================
2 ** Extended Template and Library
3 ** Thread Abstraction Class Implementation
6 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
13 ** This package is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** General Public License for more details.
18 ** === N O T E S ===========================================================
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
23 ** ========================================================================= */
25 /* === S T A R T =========================================================== */
27 #ifndef __ETL__THREAD_H_
28 #define __ETL__THREAD_H_
30 /* === H E A D E R S ======================================================= */
42 #ifdef HAVE_CREATETHREAD
46 /* === M A C R O S ========================================================= */
48 #if ( defined (HAVE_PTHREAD_CREATE) || defined (HAVE_CLONE) || defined (HAVE_CREATETHREAD) ) && !defined (NO_THREADS)
49 # define CALLISTO_THREADS
52 #define THREAD_ENTRYPOINT
54 /* === C L A S S E S & S T R U C T S ======================================= */
56 #if defined(CALLISTO_THREADS) && defined(HAVE_PTHREAD_CREATE)
57 static inline void Yield(void)
66 inline void Yield(void) { }
69 #ifdef CALLISTO_THREADS
71 #ifdef HAVE_PTHREAD_CREATE
76 typedef void* entrypoint_return;
81 entrypoint_return (*entrypoint)(void *);
84 Thread(void *(*ep)(void *)=NULL,void *context=NULL):
85 references(NULL),entrypoint(ep),context(context) { }
86 Thread(const Thread &t)
89 references=t.references;
90 entrypoint=t.entrypoint;
95 const Thread &operator=(const Thread &rhs)
104 references=rhs.references;
105 entrypoint=rhs.entrypoint;
114 references = new int;
116 pthread_create(&thread,NULL,entrypoint,context);
117 // pthread_detach(thread);
125 pthread_cancel(thread);
126 pthread_join(thread,&exit_status);
129 static void TestStop()
131 pthread_testcancel();
134 static void SyncStop()
137 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,&i);
140 static void AsyncStop()
143 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&i);
159 pthread_mutex_t mutex;
166 pthread_mutexattr_t attr;
167 pthread_mutexattr_init(&attr);
168 //#ifdef PTHREAD_PRIO_INHERIT
169 //pthread_mutexattr_setprioceiling(&attr,PTHREAD_PRIO_INHERIT);
171 #ifdef PTHREAD_MUTEX_RECURSIVE
172 pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
174 pthread_mutex_init(&mutex,&attr);
175 pthread_mutexattr_destroy(&attr);
181 { pthread_mutex_destroy(&mutex); }
185 if(!locker || locker!=pthread_self())
187 pthread_mutex_lock(&mutex);
188 locker=pthread_self();
196 { return !(bool) pthread_mutex_trylock(&mutex); }
205 pthread_mutex_unlock(&mutex);
210 #ifdef HAVE_PTHREAD_RW_LOCK_INIT
213 pthread_rwlock_t rwlock;
217 { pthread_rwlock_init(&rwlock,NULL); }
220 { pthread_rwlock_destroy(&rwlock); }
223 { pthread_rwlock_rdlock(&rwlock); }
226 { pthread_rwlock_wrlock(&rwlock); }
228 bool TryLockRead(void)
229 { return !(bool)pthread_rwlock_tryrdlock(&rwlock); }
231 bool TryLockWrite(void)
232 { return !(bool)pthread_rwlock_trywrlock(&rwlock); }
234 void UnLockWrite(void)
235 { pthread_rwlock_unlock(&rwlock); }
237 void UnLockRead(void)
238 { pthread_rwlock_unlock(&rwlock); }
242 class ReadWriteLock : public Mutex
258 bool TryLockRead(void)
259 { return TryLock(); }
261 bool TryLockWrite(void)
262 { return TryLock(); }
264 void UnLockWrite(void)
267 void UnLockRead(void)
276 pthread_mutex_t mutex;
279 { pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,NULL); }
281 { pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex);}
282 void operator()(void)
283 { pthread_cond_signal(&cond); }
286 pthread_mutex_lock(&mutex);
287 pthread_cond_wait(&cond,&mutex);
288 pthread_mutex_unlock(&mutex);
293 #else // if defined HAVE_PTHREAD
294 #ifdef HAVE_CREATETHREAD
297 #ifdef THREAD_ENTRYPOINT
298 #undef THREAD_ENTRYPOINT
300 #define THREAD_ENTRYPOINT __stdcall
304 typedef unsigned long entrypoint_return;
307 unsigned long thread;
311 entrypoint_return (THREAD_ENTRYPOINT *entrypoint)(void *);
318 static entrypoint_return THREAD_ENTRYPOINT thread_prefix(void*data)
320 Thread *thread=(Thread *)data;
323 wglMakeCurrent(thread->hdc, thread->hglrc);
325 return thread->entrypoint(thread->context);
329 Thread(entrypoint_return (THREAD_ENTRYPOINT *ep)(void *)=NULL,void *context=NULL):
330 references(NULL),entrypoint(ep),context(context) { }
331 Thread(const Thread &t)
335 references=t.references;
336 entrypoint=t.entrypoint;
342 const Thread &operator=(const Thread &rhs)
352 references=rhs.references;
353 entrypoint=rhs.entrypoint;
362 references = new int;
365 hglrc=wglGetCurrentContext();
366 hdc=wglGetCurrentDC();
369 NULL, // Security stuff
371 thread_prefix, // thread function
372 (void*)this, // thread argument
373 0, // creation option
374 &thread // thread identifier
383 TerminateThread(handle, FALSE);
390 WaitForSingleObject(handle, INFINITE);
396 static void TestStop()
400 static void SyncStop()
404 static void AsyncStop()
426 handle = CreateMutex(NULL, FALSE, NULL);
436 WaitForSingleObject(handle, INFINITE);
441 return WaitForSingleObject(handle, INFINITE)==WAIT_FAILED;
446 ReleaseMutex(handle);
451 #endif // if defined HAVE_CREATETHREAD
452 #endif // if defined HAVE_PTHREAD_CREATE
453 #endif // if defined CALLISTO_THREADS
456 #if !defined(CALLISTO_THREADS)
457 // Dummy object used when not threading
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) {}
479 bool TryLock(void){return true;}
485 class Condition : private Mutex
493 void operator()(void)
511 /* === E X T E R N S ======================================================= */
513 /* === E N D =============================================================== */