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 #ifndef ANDROID
00088 static void TestCancel()
00089 { pthread_testcancel(); }
00090 #endif
00091
00092 static Handle Self()
00093 { return (Handle)pthread_self(); }
00094
00095 public:
00096
00097 static int Create(
00098 const Handler & Function,
00099 Thread_C_R Param,
00100 Handle * const & H = 0,
00101 const bool & CreateDetached = false,
00102 const unsigned int & StackSize = 0,
00103 const bool & CancelEnable = false,
00104 const bool & CancelAsync = false
00105 )
00106 {
00107 M_Create().lock();
00108 pthread_attr_t attr;
00109 pthread_attr_init(&attr);
00110
00111 if ( CreateDetached )
00112 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00113
00114 if ( StackSize )
00115 pthread_attr_setstacksize(&attr,StackSize);
00116
00117 Instance I(Param,0,Function,CancelEnable,CancelAsync);
00118
00119 Handle h=InvalidHandle;
00120 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00121
00122 pthread_attr_destroy(&attr);
00123
00124 if(H) *H = h;
00125 if ( !R ) S_Create().acquire();
00126
00127 M_Create().unlock();
00128 return R;
00129 }
00130
00131 int Create(
00132 Thread_C_R Param,
00133 Handle * const & H = 0,
00134 const bool & CreateDetached = false,
00135 const unsigned int & StackSize = 0,
00136 const bool & CancelEnable = false,
00137 const bool & CancelAsync = false
00138 ) const
00139 {
00140 M_Create().lock();
00141 pthread_attr_t attr;
00142 pthread_attr_init(&attr);
00143
00144 if ( CreateDetached )
00145 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00146
00147 if ( StackSize )
00148 pthread_attr_setstacksize(&attr,StackSize);
00149
00150 Instance I(Param,const_cast<UThreadC *>(this),0,CancelEnable,CancelAsync);
00151
00152 Handle h=InvalidHandle;
00153 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00154
00155 pthread_attr_destroy(&attr);
00156
00157 if(H) *H = h;
00158 if ( !R ) S_Create().acquire();
00159
00160 M_Create().unlock();
00161 return R;
00162 }
00163
00164 static int Join( Handle H )
00165 { return pthread_join(H,0); }
00166
00167 #ifndef ANDROID
00168 static int Kill( Handle H )
00169 { return pthread_cancel(H); }
00170 #endif
00171
00172 static int Detach( Handle H )
00173 { return pthread_detach(H); }
00174
00175 private:
00176
00177 static const UMutex &M_Create() { static UMutex M; return M; }
00178 static USemaphore &S_Create() { static USemaphore S; return S; }
00179
00180 static void *ThreadMainHandler( Instance *Param )
00181 {
00182 Instance I(*Param);
00183 Thread_T Data(I.Data);
00184 S_Create().release();
00185
00186 #ifndef ANDROID
00187 if ( I.Flags & 1 )
00188 {
00189 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
00190
00191 if ( I.Flags & 2 )
00192 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
00193 else
00194 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
00195 }
00196 else
00197 {
00198 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
00199 }
00200 #endif
00201
00202 if ( I.Owner )
00203 I.Owner->ThreadMain(Data);
00204 else
00205 I.pFN(Data);
00206
00207 return 0;
00208 }
00209
00210 struct Instance
00211 {
00212 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 )
00213 : Data(P), Owner(O), pFN(pH), Flags(0) { if ( CE ) Flags|=1; if ( CA ) Flags|=2; }
00214
00215 Thread_C_R Data;
00216 UThreadC<Thread_T> * Owner;
00217 Handler pFN;
00218 unsigned char Flags;
00219 };
00220 };
00221
00223
00224
00225 template<>
00226 class UThreadC<void>
00227 {
00228 private:
00229 struct Instance;
00230
00231 public:
00232 typedef THREAD_HANDLE Handle;
00233 typedef void ( *Handler)();
00234
00235 virtual ~UThreadC<void>() {}
00236
00237 protected:
00238 UThreadC<void>() {}
00239
00240 virtual void ThreadMain() = 0;
00241
00242 static void Exit()
00243 { pthread_exit(0); }
00244
00245 #ifndef ANDROID
00246 static void TestCancel()
00247 { pthread_testcancel(); }
00248 #endif
00249
00250 static Handle Self()
00251 { return (Handle)pthread_self(); }
00252
00253 public:
00254
00255 static int Create(
00256 const Handler & Function,
00257 Handle * const & H = 0,
00258 const bool & CreateDetached = false,
00259 const unsigned int & StackSize = 0,
00260 const bool & CancelEnable = false,
00261 const bool & CancelAsync = false
00262 )
00263 {
00264 M_Create().lock();
00265 pthread_attr_t attr;
00266 pthread_attr_init(&attr);
00267
00268 if ( CreateDetached )
00269 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00270
00271 if ( StackSize )
00272 pthread_attr_setstacksize(&attr,StackSize);
00273
00274 Instance I(0,Function,CancelEnable,CancelAsync);
00275
00276 Handle h=InvalidHandle;
00277 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00278
00279 pthread_attr_destroy(&attr);
00280
00281 if(H) *H = h;
00282 if ( !R ) S_Create().acquire();
00283
00284 M_Create().unlock();
00285 return R;
00286 }
00287
00288 int Create(
00289 Handle * const & H = 0,
00290 const bool & CreateDetached = false,
00291 const unsigned int & StackSize = 0,
00292 const bool & CancelEnable = false,
00293 const bool & CancelAsync = false
00294 ) const
00295 {
00296 M_Create().lock();
00297 pthread_attr_t attr;
00298 pthread_attr_init(&attr);
00299
00300 if ( CreateDetached )
00301 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00302
00303 if ( StackSize )
00304 pthread_attr_setstacksize(&attr,StackSize);
00305
00306 Instance I(const_cast<UThreadC *>(this),0,CancelEnable,CancelAsync);
00307
00308 Handle h=InvalidHandle;
00309 int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00310
00311 pthread_attr_destroy(&attr);
00312
00313 if(H) *H = h;
00314 if ( !R ) S_Create().acquire();
00315
00316 M_Create().unlock();
00317 return R;
00318 }
00319
00320 int Create(
00321 unsigned long & ThreadId,
00322 Handle * const & H = 0,
00323 const bool & CreateDetached = false,
00324 const unsigned int & StackSize = 0,
00325 const bool & CancelEnable = false,
00326 const bool & CancelAsync = false
00327 ) const
00328 {
00329 M_Create().lock();
00330 pthread_attr_t attr;
00331 pthread_attr_init(&attr);
00332
00333 if ( CreateDetached )
00334 pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
00335
00336 if ( StackSize )
00337 pthread_attr_setstacksize(&attr,StackSize);
00338
00339 Instance I(const_cast<UThreadC *>(this),0,CancelEnable,CancelAsync);
00340
00341 *H = InvalidHandle;
00342 int R = pthread_create((pthread_t *)&(*H),&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
00343
00344 ThreadId = (unsigned long)*H;
00345
00346 pthread_attr_destroy(&attr);
00347
00348 if ( !R ) S_Create().acquire();
00349
00350 M_Create().unlock();
00351 return R;
00352 }
00353
00354 static int Join( Handle H )
00355 { return pthread_join(H,0); }
00356
00357 #ifndef ANDROID
00358 static int Kill( Handle H )
00359 { return pthread_cancel(H); }
00360 #endif
00361
00362 static int Detach( Handle H )
00363 { return pthread_detach(H); }
00364
00365 private:
00366
00367 static const UMutex &M_Create() { static UMutex M; return M; }
00368 static USemaphore &S_Create() { static USemaphore S; return S; }
00369
00370 static void *ThreadMainHandler( Instance *Param )
00371 {
00372 Instance I(*Param);
00373 S_Create().release();
00374
00375 #ifndef ANDROID
00376 if ( I.Flags & 1 )
00377 {
00378 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
00379
00380 if ( I.Flags & 2 )
00381 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
00382 else
00383 pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);
00384 }
00385 else
00386 {
00387 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
00388 }
00389 #endif
00390
00391 if ( I.Owner )
00392 I.Owner->ThreadMain();
00393 else
00394 I.pFN();
00395
00396 return 0;
00397 }
00398
00399 struct Instance
00400 {
00401 Instance( UThreadC<void> *const &O, const UThreadC<void>::Handler &pH = 0, const bool &CE=false, const bool &CA=false )
00402 : pFN(pH), Owner(O), Flags(0) { if ( CE ) Flags|=1; if ( CA ) Flags|=2; }
00403
00404 UThreadC<void>::Handler pFN;
00405 UThreadC<void> * Owner;
00406 unsigned char Flags;
00407
00408 };
00409 };
00410
00411 #endif // !_U_Thread_Posix_