00001 #ifndef __THREADS_POSIX_PAL_HPP__
00002 #define __THREADS_POSIX_PAL_HPP__
00003
00004 #include <pthread.h>
00005 #include <semaphore.h>
00006 #include <string.h>
00007 #include <assert.h>
00008
00009 namespace lfc
00010 {
00011 namespace posixPAL
00012 {
00013
00015
00019 namespace threads
00020 {
00021
00022 const int MAX_ERROR_CODE = 1;
00023
00024 enum ErrorCodes
00025 {
00026 errOk,
00027 errGeneric,
00028 };
00029
00030
00031 extern const char *messagesTable[MAX_ERROR_CODE + 1];
00032
00034 void* __threadProc(void *);
00035
00037 struct __StartThreadInfo
00038 {
00039 void (*proc)(void *);
00040 void *pData;
00041 };
00042
00044 struct ThreadHandle
00045 {
00046 ::pthread_t handle;
00047 bool valid;
00048
00049 ThreadHandle() : valid(false) {}
00050 bool isNull() const { return !valid; }
00051
00052 private:
00053 void operator==(const ThreadHandle &) const;
00054 };
00055
00057 struct MutexHandle
00058 {
00059 ::pthread_mutex_t handle;
00060 bool valid;
00061
00062 MutexHandle() : valid(false) {}
00063 bool isNull() const { return !valid; }
00064
00065 private:
00066 void operator==(const MutexHandle &) const;
00067 };
00068
00070
00071 struct SemHandle
00072 {
00073 ::sem_t handle;
00074 bool valid;
00075
00076 SemHandle() : valid(false) {}
00077 bool isNull() const { return !valid; }
00078
00079 private:
00080 void operator==(const SemHandle &) const;
00081 };
00082
00084 typedef ::pthread_key_t TLSKey;
00085
00086
00088 const ThreadHandle NULL_THREAD_HANDLE = ThreadHandle();
00089
00091 const MutexHandle NULL_MUTEX_HANDLE = MutexHandle();
00092
00094 const SemHandle NULL_SEM_HANDLE = SemHandle();
00095
00097 const int
00098 priorityMin = -1,
00099 priorityNormal = 0,
00100 priorityMax = 1;
00101
00102
00104
00107 inline int init()
00108 {
00109 return errOk;
00110 }
00111
00112
00114
00117 inline int cleanup()
00118 {
00119 return errOk;
00120 }
00121
00122
00124
00132 inline int createThread(ThreadHandle &handle, void (*proc)(void *), void *pData)
00133 {
00134 assert(handle.valid == false);
00135
00136 __StartThreadInfo *pInfo = new __StartThreadInfo;
00137 pInfo->proc = proc;
00138 pInfo->pData = pData;
00139
00140 ThreadHandle h;
00141 if( ::pthread_create(&h.handle, NULL, &__threadProc, pInfo) != 0 )
00142 return errGeneric;
00143
00144 h.valid = true;
00145 handle = h;
00146
00147 return errOk;
00148 }
00149
00150
00152
00157 inline int closeThread(ThreadHandle &handle)
00158 {
00159 assert(handle.valid == true);
00160
00161 if(::pthread_detach(handle.handle) == 0)
00162 {
00163 handle.valid = false;
00164 return errOk;
00165 }
00166 else
00167 return errGeneric;
00168 }
00169
00171
00180 inline int getCurrentThread(ThreadHandle &handle)
00181 {
00182
00183
00184 handle.handle = ::pthread_self();
00185 handle.valid = true;
00186 return errOk;
00187 }
00188
00189
00191
00196 inline int destroyThread(const ThreadHandle &handle)
00197 {
00198 assert(handle.valid == true);
00199 return ::pthread_cancel(handle.handle) == 0 ? errOk : errGeneric;
00200 }
00201
00203
00208 inline int joinThread(const ThreadHandle &handle)
00209 {
00210 assert(handle.valid == true);
00211
00212 if( ::pthread_join(handle.handle, NULL) == 0 )
00213 return errOk;
00214 else
00215 return errGeneric;
00216 }
00217
00218
00220
00226 inline int setThreadPriority(const ThreadHandle &handle, int priority)
00227 {
00228 assert(handle.valid == true);
00229
00230 sched_param param;
00231
00232 ::memset(¶m, 0, sizeof(param));
00233
00234 switch(priority)
00235 {
00236 case priorityMin:
00237 param.sched_priority = ::sched_get_priority_min(SCHED_OTHER);
00238 break;
00239
00240 case priorityNormal:
00241 param.sched_priority =
00242 (::sched_get_priority_min(SCHED_OTHER) +
00243 ::sched_get_priority_max(SCHED_OTHER)) / 2;
00244 break;
00245
00246 case priorityMax:
00247 param.sched_priority = ::sched_get_priority_max(SCHED_OTHER);
00248 break;
00249
00250 default:
00251 return errGeneric;
00252 }
00253
00254 if(::pthread_setschedparam(handle.handle, SCHED_OTHER, ¶m) != 0)
00255 return errGeneric;
00256
00257 return errOk;
00258 }
00259
00260
00262
00266 inline int yield()
00267 {
00268 if( ::sched_yield() == 0)
00269 return errOk;
00270
00271 return errGeneric;
00272 }
00273
00275
00280 inline int sleep(long miliseconds)
00281 {
00282 timespec ts;
00283 ts.tv_sec = miliseconds / 1000;
00284 ts.tv_nsec = (miliseconds % 1000) * 1000000;
00285 ::nanosleep(&ts, NULL);
00286
00287 return errOk;
00288 }
00289
00290
00292
00297 inline int allocTLS(TLSKey &key)
00298 {
00299 TLSKey k;
00300
00301 if( ::pthread_key_create(&k, NULL) != 0)
00302 return errGeneric;
00303
00304 key = k;
00305 return errOk;
00306 }
00307
00309
00315 inline int freeTLS(TLSKey key)
00316 {
00317 return ::pthread_key_delete(key) == 0 ? errOk : errGeneric;
00318 }
00319
00320
00322
00328 inline int setTLS(TLSKey key, void *value)
00329 {
00330 return ::pthread_setspecific(key, value) == 0 ? errOk : errGeneric;
00331 }
00332
00333
00335
00341 inline int getTLS(TLSKey key, void *&value)
00342 {
00343 void *v = ::pthread_getspecific(key);
00344 if( v == NULL)
00345 return errGeneric;
00346
00347 value = v;
00348 return errOk;
00349 }
00350
00351
00353
00362
00363 int createMutex(MutexHandle &handle);
00364
00366
00371 inline int closeMutex(MutexHandle &handle)
00372 {
00373 assert(handle.valid == true);
00374
00375 if(::pthread_mutex_destroy(&handle.handle) == 0)
00376 {
00377 handle.valid = false;
00378 return errOk;
00379 }
00380 else
00381 return errGeneric;
00382 }
00383
00384
00386
00392 inline int lockMutex(MutexHandle &handle)
00393 {
00394 assert(handle.valid == true);
00395 return ( ::pthread_mutex_lock(&handle.handle) == 0) ? errOk : errGeneric;
00396 }
00397
00398
00400
00406 inline int tryLockMutex(MutexHandle &handle, bool &bLocked)
00407 {
00408 assert(handle.valid == true);
00409 bLocked = ::pthread_mutex_trylock(&handle.handle) == 0;
00410 return errOk;
00411 }
00412
00414
00418 inline int unlockMutex(MutexHandle &handle)
00419 {
00420 assert(handle.valid == true);
00421 return ::pthread_mutex_unlock(&handle.handle) == 0 ? errOk : errGeneric;
00422 }
00423
00424
00426
00433 inline int createSemaphore(SemHandle &handle, long count)
00434 {
00435 assert(handle.valid == false);
00436
00437 if( ::sem_init(&handle.handle, 0, count) == -1)
00438 return errGeneric;
00439
00440 handle.valid = true;
00441 return errOk;
00442 }
00443
00444
00446
00451 inline int closeSemaphore(SemHandle &handle)
00452 {
00453 assert(handle.valid == true);
00454
00455 if(::sem_destroy(&handle.handle) == 0)
00456 {
00457 handle.valid = false;
00458 return errOk;
00459 }
00460 else
00461 return errGeneric;
00462 }
00463
00464
00466
00471 inline int waitSemaphore(SemHandle &handle)
00472 {
00473 assert(handle.valid == true);
00474 return ( ::sem_wait(&handle.handle) == 0 ) ? errOk : errGeneric;
00475 }
00476
00478
00484 inline int tryWaitSemaphore(SemHandle &handle, bool &bLocked)
00485 {
00486 assert(handle.valid == true);
00487 bLocked = (::sem_trywait(&handle.handle) == 0);
00488 return errOk;
00489 }
00490
00492
00497 inline int postSemaphore(SemHandle &handle)
00498 {
00499 return (::sem_post(&handle.handle) == 0) ? errOk : errGeneric;
00500 }
00501
00502
00504
00507 inline const char *message(int index)
00508 {
00509 assert(index >= 0 && index <= MAX_ERROR_CODE);
00510 return messagesTable[index];
00511 }
00512
00513
00514 }
00515 }
00516
00517 namespace pal = posixPAL;
00518
00519 }
00520
00521
00522 #endif // __THREADS_POSIX_PAL_HPP__