00001 #ifndef __SYS_PTHREAD__
00002 #define __SYS_PTHREAD__
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <errno.h>
00033 #ifdef WIN32
00034 #define HAVE_STRUCT_TIMESPEC 1
00035 #endif
00036 #include <pthread.h>
00037 #include <signal.h>
00038 #ifdef AIX
00039 #include <sys/sem.h>
00040 #else
00041 #include <semaphore.h>
00042 #endif
00043
00044 #ifdef __APPLE__
00045 #ifndef CLOCK_REALTIME
00046 #include <mach/clock.h>
00047 #include <mach/mach.h>
00048 #endif
00049 namespace
00050 {
00051 template< typename TYPE >
00052 void get_apple_realtime( TYPE & wait )
00053 {
00054 #ifdef CLOCK_REALTIME
00055 clock_gettime(CLOCK_REALTIME, &wait);
00056 #else
00057 clock_serv_t cclock;
00058 mach_timespec_t mts;
00059 host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
00060 clock_get_time(cclock, &mts);
00061 mach_port_deallocate(mach_task_self(), cclock);
00062 wait.tv_sec = mts.tv_sec;
00063 wait.tv_nsec = mts.tv_nsec;
00064 #endif
00065 }
00066 }
00067 #endif
00068
00069 #include "XrdSys/XrdSysError.hh"
00070
00071
00072
00073
00074
00075
00076
00077
00078 class XrdSysCondVar
00079 {
00080 public:
00081
00082 inline void Lock() {pthread_mutex_lock(&cmut);}
00083
00084 inline void Signal() {if (relMutex) pthread_mutex_lock(&cmut);
00085 pthread_cond_signal(&cvar);
00086 if (relMutex) pthread_mutex_unlock(&cmut);
00087 }
00088
00089 inline void Broadcast() {if (relMutex) pthread_mutex_lock(&cmut);
00090 pthread_cond_broadcast(&cvar);
00091 if (relMutex) pthread_mutex_unlock(&cmut);
00092 }
00093
00094 inline void UnLock() {pthread_mutex_unlock(&cmut);}
00095
00096 int Wait();
00097 int Wait(int sec);
00098 int WaitMS(int msec);
00099
00100 XrdSysCondVar( int relm=1,
00101 const char *cid=0
00102 ) {pthread_cond_init(&cvar, NULL);
00103 pthread_mutex_init(&cmut, NULL);
00104 relMutex = relm; condID = (cid ? cid : "unk");
00105 }
00106 ~XrdSysCondVar() {pthread_cond_destroy(&cvar);
00107 pthread_mutex_destroy(&cmut);
00108 }
00109 private:
00110
00111 pthread_cond_t cvar;
00112 pthread_mutex_t cmut;
00113 int relMutex;
00114 const char *condID;
00115 };
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 class XrdSysCondVarHelper
00130 {
00131 public:
00132
00133 inline void Lock(XrdSysCondVar *CndVar)
00134 {if (cnd) {if (cnd != CndVar) cnd->UnLock();
00135 else return;
00136 }
00137 CndVar->Lock();
00138 cnd = CndVar;
00139 };
00140
00141 inline void UnLock() {if (cnd) {cnd->UnLock(); cnd = 0;}}
00142
00143 XrdSysCondVarHelper(XrdSysCondVar *CndVar=0)
00144 {if (CndVar) CndVar->Lock();
00145 cnd = CndVar;
00146 }
00147 XrdSysCondVarHelper(XrdSysCondVar &CndVar)
00148 {CndVar.Lock();
00149 cnd = &CndVar;
00150 }
00151
00152 ~XrdSysCondVarHelper() {if (cnd) UnLock();}
00153 private:
00154 XrdSysCondVar *cnd;
00155 };
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 class XrdSysMutex
00166 {
00167 public:
00168
00169 inline int CondLock()
00170 {if (pthread_mutex_trylock( &cs )) return 0;
00171 return 1;
00172 }
00173 #ifdef __APPLE__
00174 inline int TimedLock( int wait_ms )
00175 {
00176 struct timespec wait, cur, dur;
00177 get_apple_realtime(wait);
00178 wait.tv_nsec += wait_ms * 100000;
00179 wait.tv_sec += (wait.tv_nsec / 100000000);
00180 wait.tv_nsec = wait.tv_nsec % 100000000;
00181
00182 int rc;
00183 while( ( rc = pthread_mutex_trylock( &cs ) ) == EBUSY )
00184 {
00185 get_apple_realtime(cur);
00186 if( ( cur.tv_sec > wait.tv_sec ) ||
00187 ( ( cur.tv_sec == wait.tv_sec ) && ( cur.tv_nsec >= wait.tv_nsec ) ) )
00188 return 0;
00189
00190 dur.tv_sec = wait.tv_sec - cur.tv_sec;
00191 dur.tv_nsec = wait.tv_nsec - cur.tv_nsec;
00192 if( dur.tv_nsec < 0 )
00193 {
00194 --dur.tv_sec;
00195 dur.tv_nsec += 1000000000;
00196 }
00197
00198 if( ( dur.tv_sec != 0 ) || ( dur.tv_nsec > 1000000 ) )
00199 {
00200 dur.tv_sec = 0;
00201 dur.tv_nsec = 1000000;
00202 }
00203
00204 nanosleep( &dur, 0 );
00205 }
00206
00207 return !rc;
00208 }
00209 #else
00210 inline int TimedLock(int wait_ms)
00211 {struct timespec wait;
00212 clock_gettime(CLOCK_REALTIME, &wait);
00213 wait.tv_nsec += wait_ms * 100000;
00214 wait.tv_sec += (wait.tv_nsec / 100000000);
00215 wait.tv_nsec = wait.tv_nsec % 100000000;
00216 return !pthread_mutex_timedlock(&cs, &wait);
00217 }
00218 #endif
00219
00220 inline void Lock() {pthread_mutex_lock(&cs);}
00221
00222 inline void UnLock() {pthread_mutex_unlock(&cs);}
00223
00224 XrdSysMutex() {pthread_mutex_init(&cs, NULL);}
00225 ~XrdSysMutex() {pthread_mutex_destroy(&cs);}
00226
00227 protected:
00228
00229 pthread_mutex_t cs;
00230 };
00231
00232
00233
00234
00235
00236
00237
00238
00239 class XrdSysRecMutex: public XrdSysMutex
00240 {
00241 public:
00242
00243 XrdSysRecMutex();
00244
00245 int InitRecMutex();
00246 int ReInitRecMutex();
00247
00248 };
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260 class XrdSysMutexHelper
00261 {
00262 public:
00263
00264 inline void Lock(XrdSysMutex *Mutex)
00265 {if (mtx) {if (mtx != Mutex) mtx->UnLock();
00266 else return;
00267 }
00268 Mutex->Lock();
00269 mtx = Mutex;
00270 };
00271
00272 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
00273
00274 XrdSysMutexHelper(XrdSysMutex *mutex=0)
00275 {if (mutex) mutex->Lock();
00276 mtx = mutex;
00277 }
00278 XrdSysMutexHelper(XrdSysMutex &mutex)
00279 {mutex.Lock();
00280 mtx = &mutex;
00281 }
00282
00283 ~XrdSysMutexHelper() {if (mtx) UnLock();}
00284 private:
00285 XrdSysMutex *mtx;
00286 };
00287
00288
00289
00290
00291
00292
00293
00294
00295 class XrdSysRWLock
00296 {
00297 public:
00298
00299 inline int CondReadLock()
00300 {if (pthread_rwlock_tryrdlock( &lock )) return 0;
00301 return 1;
00302 }
00303 inline int CondWriteLock()
00304 {if (pthread_rwlock_trywrlock( &lock )) return 0;
00305 return 1;
00306 }
00307
00308 inline void ReadLock() {pthread_rwlock_rdlock(&lock);}
00309 inline void WriteLock() {pthread_rwlock_wrlock(&lock);}
00310
00311 inline void ReadLock( int &status ) {status = pthread_rwlock_rdlock(&lock);}
00312 inline void WriteLock( int &status ) {status = pthread_rwlock_wrlock(&lock);}
00313
00314 inline void UnLock() {pthread_rwlock_unlock(&lock);}
00315
00316 XrdSysRWLock() {pthread_rwlock_init(&lock, NULL);}
00317 ~XrdSysRWLock() {pthread_rwlock_destroy(&lock);}
00318
00319 inline void ReInitialize()
00320 {
00321 pthread_rwlock_destroy(&lock);
00322 pthread_rwlock_init(&lock, NULL);
00323 }
00324
00325 protected:
00326
00327 pthread_rwlock_t lock;
00328 };
00329
00330
00331
00332
00333
00334
00335
00336 class XrdSysRWLockHelper
00337 {
00338 public:
00339
00340 inline void Lock(XrdSysRWLock *lock, bool rd = 1)
00341 {if (lck) {if (lck != lock) lck->UnLock();
00342 else return;
00343 }
00344 if (rd) lock->ReadLock();
00345 else lock->WriteLock();
00346 lck = lock;
00347 };
00348
00349 inline void UnLock() {if (lck) {lck->UnLock(); lck = 0;}}
00350
00351 XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd = 1)
00352 { if (l) {if (rd) l->ReadLock();
00353 else l->WriteLock();
00354 }
00355 lck = l;
00356 }
00357 XrdSysRWLockHelper(XrdSysRWLock &l, bool rd = 1)
00358 { if (rd) l.ReadLock();
00359 else l.WriteLock();
00360 lck = &l;
00361 }
00362
00363 ~XrdSysRWLockHelper() {if (lck) UnLock();}
00364 private:
00365 XrdSysRWLock *lck;
00366 };
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 #ifdef __APPLE__
00378 class XrdSysSemaphore
00379 {
00380 public:
00381
00382 int CondWait();
00383
00384 void Post();
00385
00386 void Wait();
00387
00388 static void CleanUp(void *semVar);
00389
00390 XrdSysSemaphore(int semval=1,const char *cid=0) : semVar(0, cid)
00391 {semVal = semval; semWait = 0;}
00392 ~XrdSysSemaphore() {}
00393
00394 private:
00395
00396 XrdSysCondVar semVar;
00397 int semVal;
00398 int semWait;
00399 };
00400
00401 #else
00402
00403 class XrdSysSemaphore
00404 {
00405 public:
00406
00407 inline int CondWait()
00408 {while(sem_trywait( &h_semaphore ))
00409 {if (errno == EAGAIN) return 0;
00410 if (errno != EINTR) { throw "sem_CondWait() failed";}
00411 }
00412 return 1;
00413 }
00414
00415 inline void Post() {if (sem_post(&h_semaphore))
00416 {throw "sem_post() failed";}
00417 }
00418
00419 inline void Wait() {while (sem_wait(&h_semaphore))
00420 {if (EINTR != errno)
00421 {throw "sem_wait() failed";}
00422 }
00423 }
00424
00425 XrdSysSemaphore(int semval=1, const char * =0)
00426 {if (sem_init(&h_semaphore, 0, semval))
00427 {throw "sem_init() failed";}
00428 }
00429 ~XrdSysSemaphore() {if (sem_destroy(&h_semaphore))
00430 {abort();}
00431 }
00432
00433 private:
00434
00435 sem_t h_semaphore;
00436 };
00437 #endif
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 #define XRDSYSTHREAD_BIND 0x001
00454
00455
00456
00457
00458 #define XRDSYSTHREAD_HOLD 0x002
00459
00460 class XrdSysThread
00461 {
00462 public:
00463
00464 static int Cancel(pthread_t tid) {return pthread_cancel(tid);}
00465
00466 static int Detach(pthread_t tid) {return pthread_detach(tid);}
00467
00468
00469 static int SetCancelOff() {
00470 return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
00471 };
00472
00473 static int Join(pthread_t tid, void **ret) {
00474 return pthread_join(tid, ret);
00475 };
00476
00477 static int SetCancelOn() {
00478 return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
00479 };
00480
00481 static int SetCancelAsynchronous() {
00482 return pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
00483 };
00484
00485 static int SetCancelDeferred() {
00486 return pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
00487 };
00488
00489 static void CancelPoint() {
00490 pthread_testcancel();
00491 };
00492
00493
00494 static pthread_t ID(void) {return pthread_self();}
00495
00496 static int Kill(pthread_t tid) {return pthread_cancel(tid);}
00497
00498 static unsigned long Num(void);
00499
00500 static int Run(pthread_t *, void *(*proc)(void *), void *arg,
00501 int opts=0, const char *desc = 0);
00502
00503 static int Same(pthread_t t1, pthread_t t2)
00504 {return pthread_equal(t1, t2);}
00505
00506 static void setDebug(XrdSysError *erp) {eDest = erp;}
00507
00508 static void setStackSize(size_t stsz) {stackSize = stsz;}
00509
00510 static int Signal(pthread_t tid, int snum)
00511 {return pthread_kill(tid, snum);}
00512
00513 static int Wait(pthread_t tid);
00514
00515 XrdSysThread() {}
00516 ~XrdSysThread() {}
00517
00518 private:
00519 static XrdSysError *eDest;
00520 static size_t stackSize;
00521 };
00522 #endif