_thread.h

Go to the documentation of this file.
00001 
00025 /* === S T A R T =========================================================== */
00026 
00027 #ifndef __ETL__THREAD_H_
00028 #define __ETL__THREAD_H_
00029 
00030 /* === H E A D E R S ======================================================= */
00031 
00032 #define __USE_GNU
00033 
00034 #ifdef HAVE_PTHREAD_H
00035 # include <pthread.h>
00036 #endif
00037 
00038 #ifdef HAVE_SCHED_H
00039 # include <sched.h>
00040 #endif
00041 
00042 #ifdef HAVE_CREATETHREAD
00043 # include <windows.h>
00044 #endif
00045 
00046 /* === M A C R O S ========================================================= */
00047 
00048 #if ( defined (HAVE_PTHREAD_CREATE) || defined (HAVE_CLONE) || defined (HAVE_CREATETHREAD) ) && !defined (NO_THREADS)
00049 # define CALLISTO_THREADS
00050 #endif
00051 
00052 #define THREAD_ENTRYPOINT
00053 
00054 /* === C L A S S E S & S T R U C T S ======================================= */
00055 
00056 #if defined(CALLISTO_THREADS) && defined(HAVE_PTHREAD_CREATE)
00057 static inline void Yield(void)
00058 {
00059     sched_yield();
00060     pthread_testcancel();
00061 }
00062 #else
00063 #ifdef Yield
00064     #undef Yield
00065 #endif
00066 inline void Yield(void) { }
00067 #endif
00068 
00069 #ifdef CALLISTO_THREADS
00070 
00071 #ifdef HAVE_PTHREAD_CREATE
00072 
00073 class Thread
00074 {
00075 public:
00076     typedef void* entrypoint_return;
00077 private:
00078 
00079     pthread_t thread;
00080     int *references;
00081     entrypoint_return (*entrypoint)(void *);
00082     void *context;
00083 public:
00084     Thread(void *(*ep)(void *)=NULL,void *context=NULL):
00085         references(NULL),entrypoint(ep),context(context) { }
00086     Thread(const Thread &t)
00087     {
00088         thread=t.thread;
00089         references=t.references;
00090         entrypoint=t.entrypoint;
00091         context=t.context;
00092         if(references)
00093             (*references)++;
00094     }
00095     const Thread &operator=(const Thread &rhs)
00096     {
00097         if(references)
00098         {
00099             (*references)--;
00100             if(*references==0)
00101                 stop();
00102         }
00103         thread=rhs.thread;
00104         references=rhs.references;
00105         entrypoint=rhs.entrypoint;
00106         context=rhs.context;
00107         if(references)
00108             (*references)++;
00109         return *this;
00110     }
00111 
00112     void start(void)
00113     {
00114         references = new int;
00115         *references = 1;
00116         pthread_create(&thread,NULL,entrypoint,context);
00117 //      pthread_detach(thread);
00118     }
00119 
00120     void stop(void)
00121     {
00122         delete references;
00123         references=NULL;
00124         void *exit_status;
00125         pthread_cancel(thread);
00126         pthread_join(thread,&exit_status);
00127     }
00128 
00129     static void TestStop()
00130     {
00131         pthread_testcancel();
00132     }
00133 
00134     static void SyncStop()
00135     {
00136         int i;
00137         pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,&i);
00138     }
00139 
00140     static void AsyncStop()
00141     {
00142         int i;
00143         pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&i);
00144     }
00145 
00146     ~Thread()
00147     {
00148         if(references)
00149         {
00150             (*references)--;
00151             if(*references==0)
00152                 stop();
00153         }
00154     }
00155 };
00156 
00157 class Mutex
00158 {
00159     pthread_mutex_t mutex;
00160     pthread_t locker;
00161     int depth;
00162 public:
00163 
00164     Mutex()
00165     {
00166         pthread_mutexattr_t attr;
00167         pthread_mutexattr_init(&attr);
00168         //#ifdef PTHREAD_PRIO_INHERIT
00169         //pthread_mutexattr_setprioceiling(&attr,PTHREAD_PRIO_INHERIT);
00170         //#endif
00171         #ifdef PTHREAD_MUTEX_RECURSIVE
00172         pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE);
00173         #endif
00174         pthread_mutex_init(&mutex,&attr);
00175         pthread_mutexattr_destroy(&attr);
00176         locker=0;
00177         depth=0;
00178     }
00179 
00180     ~Mutex()
00181     { pthread_mutex_destroy(&mutex); }
00182 
00183     void Lock(void)
00184     {
00185         if(!locker || locker!=pthread_self())
00186         {
00187             pthread_mutex_lock(&mutex);
00188             locker=pthread_self();
00189             depth=0;
00190             return;
00191         }
00192         depth++;
00193     }
00194 
00195     bool TryLock(void)
00196     { return !(bool) pthread_mutex_trylock(&mutex); }
00197 
00198     void UnLock(void)
00199     {
00200         if(depth)
00201         {
00202             depth--;
00203             return;
00204         }
00205         pthread_mutex_unlock(&mutex);
00206         locker=0;
00207     }
00208 };
00209 
00210 #ifdef HAVE_PTHREAD_RW_LOCK_INIT
00211 class ReadWriteLock
00212 {
00213     pthread_rwlock_t rwlock;
00214 public:
00215 
00216     ReadWriteLock()
00217     { pthread_rwlock_init(&rwlock,NULL); }
00218 
00219     ~ReadWriteLock()
00220     { pthread_rwlock_destroy(&rwlock); }
00221 
00222     void LockRead(void)
00223     { pthread_rwlock_rdlock(&rwlock); }
00224 
00225     void LockWrite(void)
00226     { pthread_rwlock_wrlock(&rwlock); }
00227 
00228     bool TryLockRead(void)
00229     { return !(bool)pthread_rwlock_tryrdlock(&rwlock); }
00230 
00231     bool TryLockWrite(void)
00232     { return !(bool)pthread_rwlock_trywrlock(&rwlock); }
00233 
00234     void UnLockWrite(void)
00235     { pthread_rwlock_unlock(&rwlock); }
00236 
00237     void UnLockRead(void)
00238     { pthread_rwlock_unlock(&rwlock); }
00239 };
00240 #else
00241 //*
00242 class ReadWriteLock : public Mutex
00243 {
00244 public:
00245 
00246     ReadWriteLock()
00247     {  }
00248 
00249     ~ReadWriteLock()
00250     {  }
00251 
00252     void LockRead(void)
00253     { Lock(); }
00254 
00255     void LockWrite(void)
00256     { Lock(); }
00257 
00258     bool TryLockRead(void)
00259     { return TryLock(); }
00260 
00261     bool TryLockWrite(void)
00262     { return TryLock(); }
00263 
00264     void UnLockWrite(void)
00265     { UnLock(); }
00266 
00267     void UnLockRead(void)
00268     { UnLock(); }
00269 };
00270 #endif
00271 
00272 /*
00273 class Condition
00274 {
00275     pthread_cond_t cond;
00276     pthread_mutex_t mutex;
00277 public:
00278     Condition()
00279     { pthread_cond_init(&cond,NULL); pthread_mutex_init(&mutex,NULL); }
00280     ~Condition()
00281     { pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex);}
00282     void operator()(void)
00283     { pthread_cond_signal(&cond); }
00284     void Wait(void)
00285     {
00286         pthread_mutex_lock(&mutex);
00287         pthread_cond_wait(&cond,&mutex);
00288         pthread_mutex_unlock(&mutex);
00289     }
00290 };
00291 */
00292 
00293 #else // if defined HAVE_PTHREAD
00294 #ifdef HAVE_CREATETHREAD
00295 
00296 
00297 #ifdef THREAD_ENTRYPOINT
00298 #undef THREAD_ENTRYPOINT
00299 #endif
00300 #define THREAD_ENTRYPOINT   __stdcall
00301 class Thread
00302 {
00303 public:
00304     typedef unsigned long entrypoint_return;
00305 private:
00306 
00307     unsigned long thread;
00308     HANDLE handle;
00309     int *references;
00310 
00311     entrypoint_return  (THREAD_ENTRYPOINT *entrypoint)(void *);
00312 
00313     void *context;
00314 
00315     HDC hdc;
00316     HGLRC hglrc;
00317 
00318     static entrypoint_return THREAD_ENTRYPOINT thread_prefix(void*data)
00319     {
00320         Thread *thread=(Thread *)data;
00321 
00322         if(thread->hglrc)
00323             wglMakeCurrent(thread->hdc, thread->hglrc);
00324 
00325         return thread->entrypoint(thread->context);
00326     }
00327 
00328 public:
00329     Thread(entrypoint_return  (THREAD_ENTRYPOINT *ep)(void *)=NULL,void *context=NULL):
00330         references(NULL),entrypoint(ep),context(context) { }
00331     Thread(const Thread &t)
00332     {
00333         thread=t.thread;
00334         handle=t.handle;
00335         references=t.references;
00336         entrypoint=t.entrypoint;
00337         context=t.context;
00338         handle=NULL;
00339         if(references)
00340             (*references)++;
00341     }
00342     const Thread &operator=(const Thread &rhs)
00343     {
00344         if(references)
00345         {
00346             (*references)--;
00347             if(*references==0)
00348                 stop();
00349         }
00350         thread=rhs.thread;
00351         handle=rhs.handle;
00352         references=rhs.references;
00353         entrypoint=rhs.entrypoint;
00354         context=rhs.context;
00355         if(references)
00356             (*references)++;
00357         return *this;
00358     }
00359 
00360     void start(void)
00361     {
00362         references = new int;
00363         *references = 1;
00364 
00365         hglrc=wglGetCurrentContext();
00366         hdc=wglGetCurrentDC();
00367 
00368         handle=CreateThread(
00369             NULL,       // Security stuff
00370             0,  // STACK
00371             thread_prefix,    // thread function
00372             (void*)this,                       // thread argument
00373             0,                    // creation option
00374             &thread                        // thread identifier
00375         );
00376     }
00377 
00378     void stop(void)
00379     {
00380         delete references;
00381         references=NULL;
00382 
00383         TerminateThread(handle, FALSE);
00384     }
00385 
00386     int wait(void)
00387     {
00388         if(handle)
00389         {
00390             WaitForSingleObject(handle, INFINITE);
00391             CloseHandle(handle);
00392         }
00393         return 0;
00394     }
00395 
00396     static void TestStop()
00397     {
00398     }
00399 
00400     static void SyncStop()
00401     {
00402     }
00403 
00404     static void AsyncStop()
00405     {
00406     }
00407 
00408     ~Thread()
00409     {
00410         if(references)
00411         {
00412             (*references)--;
00413             if(*references==0)
00414                 stop();
00415         }
00416     }
00417 };
00418 
00419 class Mutex
00420 {
00421     HANDLE handle;
00422 public:
00423 
00424     Mutex()
00425     {
00426         handle = CreateMutex(NULL, FALSE, NULL);
00427     }
00428 
00429     ~Mutex()
00430     {
00431         CloseHandle(handle);
00432     }
00433 
00434     void Lock(void)
00435     {
00436         WaitForSingleObject(handle, INFINITE);
00437     }
00438 
00439     bool TryLock(void)
00440     {
00441         return WaitForSingleObject(handle, INFINITE)==WAIT_FAILED;
00442     }
00443 
00444     void UnLock(void)
00445     {
00446         ReleaseMutex(handle);
00447     }
00448 };
00449 
00450 
00451 #endif // if defined HAVE_CREATETHREAD
00452 #endif // if defined HAVE_PTHREAD_CREATE
00453 #endif // if defined CALLISTO_THREADS
00454 
00455 
00456 #if !defined(CALLISTO_THREADS)
00457 // Dummy object used when not threading
00458 class ReadWriteLock
00459 {
00460 public:
00461 
00462     ReadWriteLock() {}
00463     ~ReadWriteLock() {}
00464     void LockRead(void) {}
00465     void LockWrite(void) {}
00466     bool TryLockRead(void) {return true;}
00467     bool TryLockWrite(void) {return true;}
00468     void UnLockRead(void) {}
00469     void UnLockWrite(void) {}
00470 };
00471 
00472 class Mutex
00473 {
00474 public:
00475 
00476     Mutex(){}
00477     ~Mutex(){}
00478     void Lock(void){}
00479     bool TryLock(void){return true;}
00480     void UnLock(void){}
00481 };
00482 
00483 #endif
00484 
00485 class Condition : private Mutex
00486 {
00487     bool flag;
00488 public:
00489     Condition()
00490     { flag=false; }
00491     ~Condition()
00492     { }
00493     void operator()(void)
00494     { flag=true; }
00495     void Wait(void)
00496     {
00497         Lock();
00498         while(!flag)Yield();
00499         flag=false;
00500         UnLock();
00501     }
00502     void WaitNext(void)
00503     {
00504         Lock();
00505         flag=false;
00506         while(!flag)Yield();
00507         UnLock();
00508     }
00509 };
00510 
00511 /* === E X T E R N S ======================================================= */
00512 
00513 /* === E N D =============================================================== */
00514 
00515 #endif

Generated on Fri Jun 22 14:33:39 2007 for ETL by  doxygen 1.5.2