Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Thread.h
00001 #ifndef GAMMA_THREAD_H_INC
00002 #define GAMMA_THREAD_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information */
00006 
00007 /***************************************************/
00008 /* \class Thread
00009     \brief STK thread class.
00010 
00011     This class provides a uniform interface for cross-platform
00012     threads.  On unix systems, the pthread library is used.  Under
00013     Windows, the C runtime threadex functions are used.
00014 
00015     Each instance of the Thread class can be used to control a single
00016     thread process.  Routines are provided to signal cancelation
00017     and/or joining with a thread, though it is not possible for this
00018     class to know the running status of a thread once it is started.
00019 
00020     For cross-platform compatability, thread functions should be
00021     declared as follows:
00022 
00023     THREAD_FUNCTION(thread_function_name)
00024 
00025     by Perry R. Cook and Gary P. Scavone, 1995 - 2005.
00026 */
00027 /***************************************************/
00028 
00029 namespace gam{
00030 
00031 #define GAM_USE_PTHREAD     (defined (__APPLE__) || defined (OSX) || defined (__LINUX__) || defined (__UNIX__))
00032 #define GAM_USE_THREADEX    (defined(WIN32))
00033 
00034 #ifdef GAM_USE_PTHREAD
00035     #include <pthread.h>
00036 #elif GAM_USE_THREADEX
00037     #include <windows.h>
00038     #include <process.h>
00039 #endif
00040 
00041 class Thread{
00042 public:
00043 
00044     typedef void * (*Function)(void * user);
00045 
00046     #ifdef GAM_USE_PTHREAD
00047         typedef pthread_t       Handle;
00048     #elif GAM_USE_THREADEX
00049         typedef unsigned long   Handle;
00050     #endif
00051 
00052     Thread()
00053     :   mHandle(0), mJoinOnDestroy(false)
00054     {}
00055     
00056     Thread(Function func, void * user = NULL)
00057     :   mHandle(0), mJoinOnDestroy(false)
00058     {   start(func, user); }
00059 
00060     ~Thread(){
00061         if(mJoinOnDestroy) join();
00062     }
00063 
00065 
00069     bool start(Function func, void * user = NULL);
00070 
00072     
00078     bool cancel();
00079 
00081     
00086     bool join();
00087 
00088 
00090     Thread& joinOnDestroy(bool v){ mJoinOnDestroy=v; return *this; }
00091 
00092 protected:
00093     Handle mHandle;
00094     bool mJoinOnDestroy;
00095 };
00096 
00097 
00098 
00099 
00100 // Implementation
00101 
00102 #ifdef GAM_USE_PTHREAD
00103 
00104 inline bool Thread::start(Thread::Function func, void * user){
00105     if(mHandle) return false;
00106     return 0 == pthread_create(&mHandle, NULL, *func, user);
00107 }
00108 
00109 inline bool Thread::cancel(){
00110     return 0 == pthread_cancel(mHandle);
00111 }
00112 
00113 inline bool Thread::join(){
00114     if(pthread_join(mHandle, NULL) == 0){
00115         mHandle = 0;
00116         return true;
00117     }
00118     return false;
00119 }
00120 
00121 
00122 #elif GAM_USE_THREADEX
00123 
00124 inline bool Thread::start(Thread::Function func, void * user){
00125     if(mHandle) return false;
00126     
00127     struct F{
00128         Thread::Function func;
00129         void * user;
00130 
00131         static unsigned _stdcall * call(void * user){
00132             F& f = *(F*)user;
00133             f.func(f.userData);
00134             return 0;
00135         }
00136     } f = { func, user };
00137     
00138     unsigned thread_id;
00139     mHandle = _beginthreadex(NULL, 0, F::call, &f, 0, &thread_id);
00140     if(mHandle) return true;
00141     return false;
00142 }
00143 
00144 inline bool Thread::cancel(){
00145     TerminateThread((HANDLE)mHandle, 0);
00146     return true;
00147 }
00148 
00149 inline bool Thread::join(){
00150     long retval = WaitForSingleObject((HANDLE)mHandle, INFINITE);
00151     if(WAIT_OBJECT_0 == retval){
00152         CloseHandle((HANDLE)mHandle);
00153         mHandle = 0;
00154         return true;
00155     }
00156     return false;
00157 }
00158 
00159 #endif
00160 
00161 } // gam::
00162 
00163 #endif
00164