UThreadC.h
Go to the documentation of this file.
00001 
00002 //  Written by Phillip Sitbon
00003 //  Copyright 2003
00004 //
00005 //  Modified by Mathieu Labbe
00006 //
00007 //  Win32/Thread.h
00008 //    - Windows thread
00009 //
00010 //  - From CreateThread Platform SDK Documentation:
00011 //
00012 //  "A thread that uses functions from the static C run-time
00013 //    libraries should use the beginthread and endthread C run-time
00014 //    functions for thread management rather than CreateThread and
00015 //    ExitThread. Failure to do so results in small memory leaks
00016 //    when ExitThread is called. Note that this is not a problem
00017 //    with the C run-time in a DLL."
00018 //
00019 //  With regards to this, I have decided to use the CreateThread
00020 //  API, unless you define _CRT_ in which case there are two
00021 //  possibilities:
00022 //
00023 //    1. Define _USE_BEGINTHREAD: Uses _beginthread/_endthread
00024 //        (said to be *unreliable* in the SDK docs)
00025 //
00026 //    2. Don't - Uses _beginthreaded/_endthreadex
00027 //
00028 //  A note about _endthread:
00029 //
00030 //    It will call CloseHandle() on exit, and if it was already
00031 //    closed then you will get an exception. To prevent this, I
00032 //    removed the CloseHandle() functionality - this means that
00033 //    a Join() WILL wait on a Detach()'ed thread.
00034 //
00036 #ifndef _U_Thread_Win32_
00037 #define _U_Thread_Win32_
00038 
00039 #include "rtabmap/utilite/Win32/UWin32.h"
00040 #include "rtabmap/utilite/USemaphore.h"
00041 #include "rtabmap/utilite/UMutex.h"
00042 
00043 inline void uSleep(unsigned int ms)
00044 {
00045         Sleep(ms);
00046 }
00047 
00048 #ifdef _CRT_
00049 # include <process.h>
00050 # ifdef _USE_BEGINTHREAD
00051 #   define THREAD_CALL                __cdecl
00052 #   define THREAD_HANDLE              uintptr_t
00053 #   define THREAD_RET_T               void
00054 #   define CREATE_THREAD_FAILED       (-1L)
00055 #   define CREATE_THREAD_ERROR        (errno)
00056 #   define CREATE_THREAD(_S,_F,_P)    ((Handle)_beginthread((void (__cdecl *)(void *))_F,_S,(void *)_P))
00057 #   define EXIT_THREAD                _endthread()
00058 #   define CLOSE_HANDLE(x)            1
00059 #   define THREAD_RETURN(x)           return
00060 # else
00061 #   define THREAD_CALL                WINAPI
00062 #   define THREAD_HANDLE              HANDLE
00063 #   define THREAD_RET_T               UINT
00064 #   define CREATE_THREAD_FAILED       (0L)
00065 #   define CREATE_THREAD_ERROR        (errno)
00066 #   define CREATE_THREAD(_S,_F,_P)    ((Handle)_beginthreadex(0,_S,(UINT (WINAPI *)(void *))_F,(void *)_P,0,0))
00067 #   define EXIT_THREAD                _endthreadex(0)
00068 #   define CLOSE_HANDLE(x)            CloseHandle(x)
00069 #   define THREAD_RETURN(x)           return(x)
00070 # endif
00071 #else
00072 # define THREAD_CALL                WINAPI
00073 # define THREAD_HANDLE              HANDLE
00074 # define THREAD_RET_T               DWORD
00075 # define CREATE_THREAD_FAILED       (0L)
00076 # define CREATE_THREAD_ERROR        GetLastError()
00077 # define CREATE_THREAD(_S,_F,_P)    ((Handle)CreateThread(0,_S,(DWORD (WINAPI *)(void *))_F,(void *)_P,0,0))
00078 # define CREATE_THREAD2(_S,_F,_P,_ID)    ((Handle)CreateThread(0,_S,(DWORD (WINAPI *)(void *))_F,(void *)_P,0,_ID))
00079 # define EXIT_THREAD                ExitThread(0)
00080 # define CLOSE_HANDLE(x)            CloseHandle(x)
00081 # define THREAD_RETURN(x)           return(x)
00082 #endif
00083 
00084 #define InvalidHandle 0
00085 
00086 template
00087 <
00088   typename Thread_T
00089 >
00090 class UTILITE_EXP UThreadC
00091 {
00092   private:
00093     struct Instance;
00094 
00095   public:
00096     typedef Thread_T              & Thread_R;
00097     typedef const Thread_T        & Thread_C_R;
00098 
00099     typedef THREAD_HANDLE Handle;
00100     typedef void (* Handler)( Thread_R );
00101 
00102   protected:
00103     UThreadC() {}
00104 
00105     virtual void ThreadMain( Thread_R ) = 0;
00106 
00107     static void Exit()
00108       { EXIT_THREAD; }
00109 
00110     static void TestCancel()
00111       { Sleep(0); }
00112 
00113     static int Self()
00114     {
00115       Handle Hnd = InvalidHandle;
00116       DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),(LPHANDLE)&Hnd,NULL,0,NULL);
00117       return Hnd;
00118 
00119       // only a pseudo-handle!
00120       //return (Handle)GetCurrentThread();
00121     }
00122 
00123   public:
00124 
00125     static int Create(
00126       const Handler       & Function,
00127       Thread_C_R            Param,
00128       Handle  * const     & H               = 0,
00129       const bool          & CreateDetached  = false,
00130       const unsigned int  & StackSize       = 0,
00131       const bool          & CancelEnable    = false,   // UNUSED
00132       const bool          & CancelAsync     = false    // UNUSED
00133     )
00134     {
00135       M_Create().lock();
00136 
00137       Instance I(Param,0,Function);
00138 
00139       Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,&I));
00140 
00141       if ( Hnd == CREATE_THREAD_FAILED )
00142       {
00143         if ( H ) *H = InvalidHandle;
00144         M_Create().unlock();
00145         return CREATE_THREAD_ERROR;
00146       }
00147 
00148       if ( H ) *H = Hnd;
00149 
00150       S_Create().Wait();
00151       M_Create().unlock();
00152 
00153       if ( CreateDetached ) CLOSE_HANDLE(Hnd);
00154       return 0;
00155     }
00156 
00157     int Create(
00158       Thread_C_R            Param,
00159       Handle  * const     & H               = 0,
00160       const bool          & CreateDetached  = false,
00161       const unsigned int  & StackSize       = 0,
00162       const bool          & CancelEnable    = false,   // UNUSED
00163       const bool          & CancelAsync     = false    // UNUSED
00164     ) const
00165     {
00166       M_Create().lock();
00167 
00168       Instance I(Param,const_cast<UThreadC *>(this));
00169 
00170       Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,&I));
00171 
00172       if ( Hnd == CREATE_THREAD_FAILED )
00173       {
00174         if ( H ) *H = InvalidHandle;
00175         M_Create().unlock();
00176         return CREATE_THREAD_ERROR;
00177       }
00178 
00179       if ( H ) *H = Hnd;
00180 
00181       S_Create().Wait();
00182       M_Create().unlock();
00183 
00184       if ( CreateDetached ) CLOSE_HANDLE(Hnd);
00185       return 0;
00186     }
00187 
00188     static int Join( const Handle &H )
00189     {
00190       DWORD R = WaitForSingleObject((HANDLE)H,INFINITE);
00191 
00192       if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) )
00193       {
00194         CLOSE_HANDLE(H);
00195         return 0;
00196       }
00197 
00198       if ( R == WAIT_TIMEOUT ) return EAGAIN;
00199       return EINVAL;
00200     }
00201 
00202     static int Kill( const Handle &H )
00203       { return TerminateThread((HANDLE)H,0) ? 0 : EINVAL; }
00204 
00205     static int Detach( const Handle &H )
00206       { return (CLOSE_HANDLE(H)?0:EINVAL); }
00207 
00208   private:
00209 
00210     static const UMutex &M_Create()      { static UMutex M; return M; }
00211     static const USemaphore &S_Create()  { static USemaphore S; return S; }
00212 
00213     static THREAD_RET_T THREAD_CALL ThreadMainHandler( Instance *Param )
00214     {
00215       Instance  I(*Param);
00216       Thread_T  Data(I.Data);
00217       S_Create().Post();
00218 
00219       if ( I.Owner )
00220         I.Owner->ThreadMain(Data);
00221       else
00222         I.pFN(Data);
00223 
00224       Exit();
00225       THREAD_RETURN(0);
00226     }
00227 
00228     struct Instance
00229     {
00230       Instance( Thread_C_R P, UThreadC<Thread_T> *const &O, const typename UThreadC<Thread_T>::Handler &pH = 0 )
00231         : pFN(pH), Data(P), Owner(O) {}
00232 
00233       typename UThreadC<Thread_T>::Handler             pFN;
00234       typename UThreadC<Thread_T>::Thread_C_R          Data;
00235       UThreadC<Thread_T>                    * Owner;
00236 
00237     };
00238 };
00239 
00241 //  Explicit Specialization of void
00242 //
00243 template<>
00244 class UTILITE_EXP UThreadC<void>
00245 {
00246   private:
00247     struct Instance;
00248 
00249   public:
00250     typedef THREAD_HANDLE Handle;
00251     typedef void ( *Handler)();
00252 
00253     virtual ~UThreadC<void>() {}
00254 
00255   protected:
00256     UThreadC<void>() {}
00257 
00258     virtual void ThreadMain() = 0;
00259 
00260     static void Exit()
00261       { EXIT_THREAD; }
00262 
00263     static void TestCancel()
00264       { Sleep(0); }
00265 
00266     static int Self()
00267     {
00268       return (int)GetCurrentThreadId();
00269       //Handle Hnd = InvalidHandle;
00270       //DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),GetCurrentProcess(),(LPHANDLE)&Hnd,NULL,0,NULL);
00271       //return Hnd;
00272 
00273       // only a pseudo-handle!
00274       //return (Handle)GetCurrentThread();
00275     }
00276 
00277   public:
00278 
00279     static int Create(
00280       const Handler       & Function,
00281       Handle  * const     & H               = 0,
00282       const bool          & CreateDetached  = false,
00283       const unsigned int  & StackSize       = 0,
00284       const bool          & CancelEnable    = false,   // UNUSED
00285       const bool          & CancelAsync     = false    // UNUSED
00286     )
00287     {
00288       Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler_S,Function));
00289 
00290       if ( Hnd == CREATE_THREAD_FAILED )
00291       {
00292         if ( H ) *H = InvalidHandle;
00293         return (int)CREATE_THREAD_ERROR;
00294       }
00295 
00296       if ( H ) *H = Hnd;
00297       if ( CreateDetached ) CLOSE_HANDLE(Hnd);
00298       return 0;
00299     }
00300 
00301     int Create(
00302       Handle  * const     & H               = 0,
00303       const bool          & CreateDetached  = false,
00304       const unsigned int  & StackSize       = 0,
00305       const bool          & CancelEnable    = false,   // UNUSED
00306       const bool          & CancelAsync     = false    // UNUSED
00307     ) const
00308     {
00309       Handle Hnd(CREATE_THREAD(StackSize,ThreadMainHandler,this));
00310 
00311       if ( Hnd == CREATE_THREAD_FAILED )
00312       {
00313         if ( H ) *H = InvalidHandle;
00314         return (int)CREATE_THREAD_ERROR;
00315       }
00316 
00317       if ( H ) *H = Hnd;
00318       if ( CreateDetached ) CLOSE_HANDLE(Hnd);
00319       Self();
00320       return 0;
00321     }
00322 
00323     int Create(
00324       unsigned long       & ThreadId,
00325       Handle  * const     & H               = 0,
00326       const bool          & CreateDetached  = false,
00327       const unsigned int  & StackSize       = 0,
00328       const bool          & CancelEnable    = false,   // UNUSED
00329       const bool          & CancelAsync     = false    // UNUSED
00330     ) const
00331     {
00332         *H = InvalidHandle;
00333         int id;
00334         *H = CREATE_THREAD2(StackSize,ThreadMainHandler,this, (LPDWORD)&id);
00335         ThreadId = (unsigned long)id;
00336 
00337       if ( *H == CREATE_THREAD_FAILED )
00338       {
00339           *H = InvalidHandle;
00340         return (int)CREATE_THREAD_ERROR;
00341       }
00342 
00343       if ( CreateDetached ) CLOSE_HANDLE(*H);
00344       return 0;
00345     }
00346 
00347     static int Join( const Handle &H )
00348     {
00349       DWORD R = WaitForSingleObject((HANDLE)H,INFINITE);
00350 
00351       if ( (R == WAIT_OBJECT_0) || (R == WAIT_ABANDONED) )
00352       {
00353         CLOSE_HANDLE(H);
00354         return 0;
00355       }
00356 
00357       if ( R == WAIT_TIMEOUT ) return EAGAIN;
00358       return EINVAL;
00359     }
00360 
00361     static int Kill( const Handle &H )
00362       { return TerminateThread((HANDLE)H,0) ? 0 : EINVAL; }
00363 
00364     static int Detach( const Handle &H )
00365       { return (CLOSE_HANDLE(H)?0:EINVAL); }
00366 
00367   private:
00368 
00369     static THREAD_RET_T THREAD_CALL ThreadMainHandler( UThreadC<void> *Param )
00370     {
00371       Param->ThreadMain();
00372       Exit();
00373       THREAD_RETURN(0);
00374     }
00375 
00376     static THREAD_RET_T THREAD_CALL ThreadMainHandler_S( Handler Param )
00377     {
00378       Param();
00379       Exit();
00380       THREAD_RETURN(0);
00381     }
00382 };
00383 
00384 #endif // !_U_Thread_Win32_


rtabmap
Author(s): Mathieu Labbe
autogenerated on Sat Jul 23 2016 11:44:28