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