00001
00002
00003
00004
00005
00006
00007
00008
00009
00011
00012 #ifndef _U_Thread_Posix_
00013 #define _U_Thread_Posix_
00014
00015 #include "rtabmap/utilite/USemaphore.h"
00016 #include "rtabmap/utilite/UMutex.h"
00017
00018 #include <pthread.h>
00019
00023 inline void uSleep(unsigned int ms)
00024 {
00025 struct timespec req;
00026 struct timespec rem;
00027 req.tv_sec = ms / 1000;
00028 req.tv_nsec = (ms - req.tv_sec * 1000) * 1000 * 1000;
00029 nanosleep (&req, &rem);
00030 }
00031
00035 inline void uSleepMicro(unsigned int us)
00036 {
00037 struct timespec req;
00038 struct timespec rem;
00039 req.tv_sec = us / 1000000;
00040 req.tv_nsec = (us - req.tv_sec * 1000000) * 1000;
00041 nanosleep (&req, &rem);
00042 }
00043
00047 inline void uSleepNano(unsigned int ns)
00048 {
00049 struct timespec req;
00050 struct timespec rem;
00051 req.tv_sec = ns / 1000000000;
00052 req.tv_nsec = (ns - req.tv_sec * 1000000000);
00053 nanosleep (&req, &rem);
00054 }
00055
00056
00057 #define InvalidHandle 0
00058 #define THREAD_HANDLE pthread_t
00059
00060 typedef void *( * pthread_fn )( void * );
00061
00062 template
00063 <
00064 typename Thread_T
00065 >
00066 class UThreadC
00067 {
00068 private:
00069 struct Instance;
00070
00071 public:
00072 typedef Thread_T & Thread_R;
00073 typedef const Thread_T & Thread_C_R;
00074
00075 typedef THREAD_HANDLE Handle;
00076 typedef void ( *Handler)( Thread_R );
00077
00078 virtual ~UThreadC() {}
00079
00080 protected:
00081 UThreadC() {}
00082
00083 virtual void ThreadMain( Thread_R ) = 0;
00084
00085 static void Exit()
00086 { pthread_exit(0); }
00087
00088 static void TestCancel()
00089 { pthread_testcancel(); }
00090
00091 static Handle Self()
00092 { return (Handle)pthread_self(); }
00093
00094 public:
00095
00096 static int Create(
00097 const Handler & Function,
00098 Thread_C_R Param,
00099 Handle * const & H = 0,
00100 const bool & CreateDetached = false,
00101 const unsigned int & StackSize = 0,
00102 const bool & CancelEnable = false,
00103 const bool & CancelAsync = false
00104 )
00105 {
00106 M_Create().lock();
00107 pthread_attr_t attr;
00108 pthread_attr_init(&attr);
00109
00110 if ( CreateDetached )
00111 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00112
00113 if ( StackSize )
00114 pthread_attr_setstacksize(&attr,StackSize);
00115
00116 Instance I(Param,0,Function,CancelEnable,CancelAsync);
00117
00118 Handle h=InvalidHandle;
00119 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00120
00121 pthread_attr_destroy(&attr);
00122
00123 if(H) *H = h;
00124 if ( !R ) S_Create().acquire();
00125
00126 M_Create().unlock();
00127 return R;
00128 }
00129
00130 int Create(
00131 Thread_C_R Param,
00132 Handle * const & H = 0,
00133 const bool & CreateDetached = false,
00134 const unsigned int & StackSize = 0,
00135 const bool & CancelEnable = false,
00136 const bool & CancelAsync = false
00137 ) const
00138 {
00139 M_Create().lock();
00140 pthread_attr_t attr;
00141 pthread_attr_init(&attr);
00142
00143 if ( CreateDetached )
00144 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00145
00146 if ( StackSize )
00147 pthread_attr_setstacksize(&attr,StackSize);
00148
00149 Instance I(Param,const_cast<UThreadC *>(this),0,CancelEnable,CancelAsync);
00150
00151 Handle h=InvalidHandle;
00152 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00153
00154 pthread_attr_destroy(&attr);
00155
00156 if(H) *H = h;
00157 if ( !R ) S_Create().acquire();
00158
00159 M_Create().unlock();
00160 return R;
00161 }
00162
00163 static int Join( Handle H )
00164 { return pthread_join(H,0); }
00165
00166 static int Kill( Handle H )
00167 { return pthread_cancel(H); }
00168
00169 static int Detach( Handle H )
00170 { return pthread_detach(H); }
00171
00172 private:
00173
00174 static const UMutex &M_Create() { static UMutex M; return M; }
00175 static USemaphore &S_Create() { static USemaphore S; return S; }
00176
00177 static void *ThreadMainHandler( Instance *Param )
00178 {
00179 Instance I(*Param);
00180 Thread_T Data(I.Data);
00181 S_Create().release();
00182
00183 if ( I.Flags & 1 )
00184 {
00185 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
00186
00187 if ( I.Flags & 2 )
00188 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
00189 else
00190 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
00191 }
00192 else
00193 {
00194 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
00195 }
00196
00197 if ( I.Owner )
00198 I.Owner->ThreadMain(Data);
00199 else
00200 I.pFN(Data);
00201
00202 return 0;
00203 }
00204
00205 struct Instance
00206 {
00207 Instance( Thread_C_R P, UThreadC<Thread_T> *const &O, const UThreadC<Thread_T>::Handler &pH = 0, const bool &CE=false, const bool &CA=false )
00208 : Data(P), Owner(O), pFN(pH), Flags(0) { if ( CE ) Flags|=1; if ( CA ) Flags|=2; }
00209
00210 Thread_C_R Data;
00211 UThreadC<Thread_T> * Owner;
00212 Handler pFN;
00213 unsigned char Flags;
00214 };
00215 };
00216
00218
00219
00220 template<>
00221 class UThreadC<void>
00222 {
00223 private:
00224 struct Instance;
00225
00226 public:
00227 typedef THREAD_HANDLE Handle;
00228 typedef void ( *Handler)();
00229
00230 virtual ~UThreadC<void>() {}
00231
00232 protected:
00233 UThreadC<void>() {}
00234
00235 virtual void ThreadMain() = 0;
00236
00237 static void Exit()
00238 { pthread_exit(0); }
00239
00240 static void TestCancel()
00241 { pthread_testcancel(); }
00242
00243 static Handle Self()
00244 { return (Handle)pthread_self(); }
00245
00246 public:
00247
00248 static int Create(
00249 const Handler & Function,
00250 Handle * const & H = 0,
00251 const bool & CreateDetached = false,
00252 const unsigned int & StackSize = 0,
00253 const bool & CancelEnable = false,
00254 const bool & CancelAsync = false
00255 )
00256 {
00257 M_Create().lock();
00258 pthread_attr_t attr;
00259 pthread_attr_init(&attr);
00260
00261 if ( CreateDetached )
00262 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00263
00264 if ( StackSize )
00265 pthread_attr_setstacksize(&attr,StackSize);
00266
00267 Instance I(0,Function,CancelEnable,CancelAsync);
00268
00269 Handle h=InvalidHandle;
00270 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00271
00272 pthread_attr_destroy(&attr);
00273
00274 if(H) *H = h;
00275 if ( !R ) S_Create().acquire();
00276
00277 M_Create().unlock();
00278 return R;
00279 }
00280
00281 int Create(
00282 Handle * const & H = 0,
00283 const bool & CreateDetached = false,
00284 const unsigned int & StackSize = 0,
00285 const bool & CancelEnable = false,
00286 const bool & CancelAsync = false
00287 ) const
00288 {
00289 M_Create().lock();
00290 pthread_attr_t attr;
00291 pthread_attr_init(&attr);
00292
00293 if ( CreateDetached )
00294 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00295
00296 if ( StackSize )
00297 pthread_attr_setstacksize(&attr,StackSize);
00298
00299 Instance I(const_cast<UThreadC *>(this),0,CancelEnable,CancelAsync);
00300
00301 Handle h=InvalidHandle;
00302 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00303
00304 pthread_attr_destroy(&attr);
00305
00306 if(H) *H = h;
00307 if ( !R ) S_Create().acquire();
00308
00309 M_Create().unlock();
00310 return R;
00311 }
00312
00313 int Create(
00314 unsigned long & ThreadId,
00315 Handle * const & H = 0,
00316 const bool & CreateDetached = false,
00317 const unsigned int & StackSize = 0,
00318 const bool & CancelEnable = false,
00319 const bool & CancelAsync = false
00320 ) const
00321 {
00322 M_Create().lock();
00323 pthread_attr_t attr;
00324 pthread_attr_init(&attr);
00325
00326 if ( CreateDetached )
00327 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00328
00329 if ( StackSize )
00330 pthread_attr_setstacksize(&attr,StackSize);
00331
00332 Instance I(const_cast<UThreadC *>(this),0,CancelEnable,CancelAsync);
00333
00334 *H = InvalidHandle;
00335 int R = pthread_create((pthread_t *)&(*H),&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00336
00337 ThreadId = (unsigned long)*H;
00338
00339 pthread_attr_destroy(&attr);
00340
00341 if ( !R ) S_Create().acquire();
00342
00343 M_Create().unlock();
00344 return R;
00345 }
00346
00347 static int Join( Handle H )
00348 { return pthread_join(H,0); }
00349
00350 static int Kill( Handle H )
00351 { return pthread_cancel(H); }
00352
00353 static int Detach( Handle H )
00354 { return pthread_detach(H); }
00355
00356 private:
00357
00358 static const UMutex &M_Create() { static UMutex M; return M; }
00359 static USemaphore &S_Create() { static USemaphore S; return S; }
00360
00361 static void *ThreadMainHandler( Instance *Param )
00362 {
00363 Instance I(*Param);
00364 S_Create().release();
00365
00366 if ( I.Flags & 1 )
00367 {
00368 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
00369
00370 if ( I.Flags & 2 )
00371 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
00372 else
00373 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
00374 }
00375 else
00376 {
00377 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
00378 }
00379
00380 if ( I.Owner )
00381 I.Owner->ThreadMain();
00382 else
00383 I.pFN();
00384
00385 return 0;
00386 }
00387
00388 struct Instance
00389 {
00390 Instance( UThreadC<void> *const &O, const UThreadC<void>::Handler &pH = 0, const bool &CE=false, const bool &CA=false )
00391 : pFN(pH), Owner(O), Flags(0) { if ( CE ) Flags|=1; if ( CA ) Flags|=2; }
00392
00393 UThreadC<void>::Handler pFN;
00394 UThreadC<void> * Owner;
00395 unsigned char Flags;
00396
00397 };
00398 };
00399
00400 #endif // !_U_Thread_Posix_