Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

XrdSysPthread.hh

Go to the documentation of this file.
00001 #ifndef __SYS_PTHREAD__
00002 #define __SYS_PTHREAD__
00003 /******************************************************************************/
00004 /*                                                                            */
00005 /*                      X r d S y s P t h r e a d . h h                       */
00006 /*                                                                            */
00007 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University  */
00008 /*       All Rights Reserved. See XrdInfo.cc for complete License Terms       */
00009 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00010 /*              DE-AC03-76-SFO0515 with the Department of Energy              */
00011 /******************************************************************************/
00012   
00013 //        $Id$
00014 
00015 #include <errno.h>
00016 #ifdef WIN32
00017 #define HAVE_STRUCT_TIMESPEC 1
00018 #endif
00019 #include <pthread.h>
00020 #include <signal.h>
00021 #ifdef AIX
00022 #include <sys/sem.h>
00023 #else
00024 #include <semaphore.h>
00025 #endif
00026 
00027 #include "XrdSys/XrdSysError.hh"
00028 
00029 /******************************************************************************/
00030 /*                         X r d S y s C o n d V a r                          */
00031 /******************************************************************************/
00032   
00033 // XrdSysCondVar implements the standard POSIX-compliant condition variable.
00034 //               Methods correspond to the equivalent pthread condvar functions.
00035 
00036 class XrdSysCondVar
00037 {
00038 public:
00039 
00040 inline void  Lock()           {pthread_mutex_lock(&cmut);}
00041 
00042 inline void  Signal()         {if (relMutex) pthread_mutex_lock(&cmut);
00043                                pthread_cond_signal(&cvar);
00044                                if (relMutex) pthread_mutex_unlock(&cmut);
00045                               }
00046 
00047 inline void  Broadcast()      {if (relMutex) pthread_mutex_lock(&cmut);
00048                                pthread_cond_broadcast(&cvar);
00049                                if (relMutex) pthread_mutex_unlock(&cmut);
00050                               }
00051 
00052 inline void  UnLock()         {pthread_mutex_unlock(&cmut);}
00053 
00054        int   Wait();
00055        int   Wait(int sec);
00056        int   WaitMS(int msec);
00057 
00058       XrdSysCondVar(      int   relm=1, // 0->Caller will handle lock/unlock
00059                     const char *cid=0   // ID string for debugging only
00060                    ) {pthread_cond_init(&cvar, NULL);
00061                       pthread_mutex_init(&cmut, NULL);
00062                       relMutex = relm; condID = (cid ? cid : "unk");
00063                      }
00064      ~XrdSysCondVar() {pthread_cond_destroy(&cvar);
00065                        pthread_mutex_destroy(&cmut);
00066                       }
00067 private:
00068 
00069 pthread_cond_t  cvar;
00070 pthread_mutex_t cmut;
00071 int             relMutex;
00072 const char     *condID;
00073 };
00074 
00075 
00076 
00077 /******************************************************************************/
00078 /*                     X r d S y s C o n d V a r H e l p e r                  */
00079 /******************************************************************************/
00080 
00081 // XrdSysCondVarHelper is used to implement monitors with the Lock of a a condvar.
00082 //                     Monitors are used to lock
00083 //                     whole regions of code (e.g., a method) and automatically
00084 //                     unlock with exiting the region (e.g., return). The
00085 //                     methods should be self-evident.
00086   
00087 class XrdSysCondVarHelper
00088 {
00089 public:
00090 
00091 inline void   Lock(XrdSysCondVar *CndVar)
00092                   {if (cnd) {if (cnd != CndVar) cnd->UnLock();
00093                                 else return;
00094                             }
00095                    CndVar->Lock();
00096                    cnd = CndVar;
00097                   };
00098 
00099 inline void UnLock() {if (cnd) {cnd->UnLock(); cnd = 0;}}
00100 
00101             XrdSysCondVarHelper(XrdSysCondVar *CndVar=0)
00102                  {if (CndVar) CndVar->Lock();
00103                   cnd = CndVar;
00104                  }
00105             XrdSysCondVarHelper(XrdSysCondVar &CndVar) {
00106                  CndVar.Lock();
00107                  cnd = &CndVar;
00108                  }
00109 
00110            ~XrdSysCondVarHelper() {if (cnd) UnLock();}
00111 private:
00112 XrdSysCondVar *cnd;
00113 };
00114 
00115 
00116 /******************************************************************************/
00117 /*                           X r d S y s M u t e x                            */
00118 /******************************************************************************/
00119 
00120 // XrdSysMutex implements the standard POSIX mutex. The methods correspond
00121 //             to the equivalent pthread mutex functions.
00122   
00123 class XrdSysMutex
00124 {
00125 public:
00126 
00127 inline int CondLock()
00128        {if (pthread_mutex_trylock( &cs )) return 0;
00129         return 1;
00130        }
00131 
00132 inline void   Lock() {pthread_mutex_lock(&cs);}
00133 
00134 inline void UnLock() {pthread_mutex_unlock(&cs);}
00135 
00136         XrdSysMutex() {pthread_mutex_init(&cs, NULL);}
00137        ~XrdSysMutex() {pthread_mutex_destroy(&cs);}
00138 
00139 protected:
00140 
00141 pthread_mutex_t cs;
00142 };
00143 
00144 /******************************************************************************/
00145 /*                         X r d S y s R e c M u t e x                        */
00146 /******************************************************************************/
00147 
00148 // XrdSysRecMutex implements the recursive POSIX mutex. The methods correspond
00149 //             to the equivalent pthread mutex functions.
00150   
00151 class XrdSysRecMutex: public XrdSysMutex
00152 {
00153 public:
00154 
00155 XrdSysRecMutex();
00156 
00157 };
00158 
00159 
00160 /******************************************************************************/
00161 /*                     X r d S y s M u t e x H e l p e r                      */
00162 /******************************************************************************/
00163 
00164 // XrdSysMutexHelper us ised to implement monitors. Monitors are used to lock
00165 //                   whole regions of code (e.g., a method) and automatically
00166 //                   unlock with exiting the region (e.g., return). The
00167 //                   methods should be self-evident.
00168   
00169 class XrdSysMutexHelper
00170 {
00171 public:
00172 
00173 inline void   Lock(XrdSysMutex *Mutex)
00174                   {if (mtx) {if (mtx != Mutex) mtx->UnLock();
00175                                 else return;
00176                             }
00177                    Mutex->Lock();
00178                    mtx = Mutex;
00179                   };
00180 
00181 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
00182 
00183             XrdSysMutexHelper(XrdSysMutex *mutex=0)
00184                  {if (mutex) mutex->Lock();
00185                   mtx = mutex;
00186                  }
00187             XrdSysMutexHelper(XrdSysMutex &mutex) {
00188                  mutex.Lock();
00189                  mtx = &mutex;
00190                  }
00191 
00192            ~XrdSysMutexHelper() {if (mtx) UnLock();}
00193 private:
00194 XrdSysMutex *mtx;
00195 };
00196 
00197 /******************************************************************************/
00198 /*                           X r d S y s R W L o c k                          */
00199 /******************************************************************************/
00200 
00201 // XrdSysRWLock implements the standard POSIX wrlock mutex. The methods correspond
00202 //             to the equivalent pthread wrlock functions.
00203   
00204 class XrdSysRWLock
00205 {
00206 public:
00207 
00208 inline int CondReadLock()
00209        {if (pthread_rwlock_tryrdlock( &lock )) return 0;
00210         return 1;
00211        }
00212 inline int CondWriteLock()
00213        {if (pthread_rwlock_trywrlock( &lock )) return 0;
00214         return 1;
00215        }
00216 
00217 inline void  ReadLock() {pthread_rwlock_rdlock(&lock);}
00218 inline void  WriteLock() {pthread_rwlock_wrlock(&lock);}
00219 
00220 inline void UnLock() {pthread_rwlock_unlock(&lock);}
00221 
00222         XrdSysRWLock() {pthread_rwlock_init(&lock, NULL);}
00223        ~XrdSysRWLock() {pthread_rwlock_destroy(&lock);}
00224 
00225 protected:
00226 
00227 pthread_rwlock_t lock;
00228 };
00229 
00230 /******************************************************************************/
00231 /*                     X r d S y s W R L o c k H e l p e r                    */
00232 /******************************************************************************/
00233 
00234 // XrdSysWRLockHelper : helper class for XrdSysRWLock
00235   
00236 class XrdSysRWLockHelper
00237 {
00238 public:
00239 
00240 inline void   Lock(XrdSysRWLock *lock, bool rd = 1)
00241                   {if (lck) {if (lck != lock) lck->UnLock();
00242                                 else return;
00243                             }
00244                    if (rd) lock->ReadLock();
00245                       else lock->WriteLock();
00246                    lck = lock;
00247                   };
00248 
00249 inline void UnLock() {if (lck) {lck->UnLock(); lck = 0;}}
00250 
00251             XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd = 1)
00252                  { if (l) {if (rd) l->ReadLock();
00253                               else l->WriteLock();
00254                           }
00255                    lck = l;
00256                  }
00257             XrdSysRWLockHelper(XrdSysRWLock &l, bool rd = 1)
00258                  { if (rd) l.ReadLock();
00259                       else l.WriteLock();
00260                    lck = &l;
00261                  }
00262 
00263            ~XrdSysRWLockHelper() {if (lck) UnLock();}
00264 private:
00265 XrdSysRWLock *lck;
00266 };
00267 
00268 /******************************************************************************/
00269 /*                       X r d S y s S e m a p h o r e                        */
00270 /******************************************************************************/
00271 
00272 // XrdSysSemaphore implements the classic counting semaphore. The methods
00273 //                 should be self-evident. Note that on certain platforms
00274 //                 semaphores need to be implemented based on condition
00275 //                 variables since no native implementation is available.
00276   
00277 #ifdef __macos__
00278 class XrdSysSemaphore
00279 {
00280 public:
00281 
00282        int  CondWait();
00283 
00284        void Post();
00285 
00286        void Wait();
00287 
00288   XrdSysSemaphore(int semval=1,const char *cid=0) : semVar(0, cid)
00289                                   {semVal = semval; semWait = 0;}
00290  ~XrdSysSemaphore() {}
00291 
00292 private:
00293 
00294 XrdSysCondVar semVar;
00295 int           semVal;
00296 int           semWait;
00297 };
00298 
00299 #else
00300 
00301 class XrdSysSemaphore
00302 {
00303 public:
00304 
00305 inline int  CondWait()
00306        {while(sem_trywait( &h_semaphore ))
00307              {if (errno == EAGAIN) return 0;
00308               if (errno != EINTR) { throw "sem_CondWait() failed";}
00309              }
00310         return 1;
00311        }
00312 
00313 inline void Post() {if (sem_post(&h_semaphore))
00314                        {throw "sem_post() failed";}
00315                    }
00316 
00317 inline void Wait() {while (sem_wait(&h_semaphore))
00318                           {if (EINTR != errno) 
00319                               {throw "sem_wait() failed";}
00320                           }
00321                    }
00322 
00323   XrdSysSemaphore(int semval=1, const char * =0)
00324                                {if (sem_init(&h_semaphore, 0, semval))
00325                                    {throw "sem_init() failed";}
00326                                }
00327  ~XrdSysSemaphore() {if (sem_destroy(&h_semaphore))
00328                        {throw "sem_destroy() failed";}
00329                    }
00330 
00331 private:
00332 
00333 sem_t h_semaphore;
00334 };
00335 #endif
00336 
00337 /******************************************************************************/
00338 /*                          X r d S y s T h r e a d                           */
00339 /******************************************************************************/
00340   
00341 // The C++ standard makes it impossible to link extern "C" methods with C++
00342 // methods. Thus, making a full thread object is nearly impossible. So, this
00343 // object is used as the thread manager. Since it is static for all intense
00344 // and purposes, one does not need to create an instance of it.
00345 //
00346 
00347 // Options to Run()
00348 //
00349 // BIND creates threads that are bound to a kernel thread.
00350 //
00351 #define XRDSYSTHREAD_BIND 0x001
00352 
00353 // HOLD creates a thread that needs to be joined to get its ending value.
00354 //      Otherwise, a detached thread is created.
00355 //
00356 #define XRDSYSTHREAD_HOLD 0x002
00357 
00358 class XrdSysThread
00359 {
00360 public:
00361 
00362 static int          Cancel(pthread_t tid) {return pthread_cancel(tid);}
00363 
00364 static int          Detach(pthread_t tid) {return pthread_detach(tid);}
00365 
00366 
00367 static  int  SetCancelOff() {
00368       return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
00369  };
00370 
00371 static  int  Join(pthread_t tid, void **ret) {
00372    return pthread_join(tid, ret);
00373  };
00374 
00375 static  int  SetCancelOn() {
00376       return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
00377  };
00378 
00379 static  int  SetCancelAsynchronous() {
00380       return pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
00381  };
00382 
00383 static int  SetCancelDeferred() {
00384       return pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
00385  };
00386 
00387 static void  CancelPoint() {
00388       pthread_testcancel();
00389  };
00390 
00391 
00392 static pthread_t    ID(void)              {return pthread_self();}
00393 
00394 static int          Kill(pthread_t tid)   {return pthread_cancel(tid);}
00395 
00396 static unsigned long Num(void)
00397                        {if (!initDone) doInit();
00398                         return (unsigned long)pthread_getspecific(threadNumkey);
00399                        }
00400 
00401 static int          Run(pthread_t *, void *(*proc)(void *), void *arg, 
00402                         int opts=0, const char *desc = 0);
00403 
00404 static int          Same(pthread_t t1, pthread_t t2)
00405                         {return pthread_equal(t1, t2);}
00406 
00407 static void         setDebug(XrdSysError *erp) {eDest = erp;}
00408 
00409 static void         setStackSize(size_t stsz) {stackSize = stsz;}
00410 
00411 static int          Signal(pthread_t tid, int snum)
00412                        {return pthread_kill(tid, snum);}
00413  
00414 static int          Wait(pthread_t tid);
00415 
00416                     XrdSysThread() {}
00417                    ~XrdSysThread() {}
00418 
00419 private:
00420 static void          doInit(void);
00421 static XrdSysError  *eDest;
00422 static pthread_key_t threadNumkey;
00423 static size_t        stackSize;
00424 static int           initDone;
00425 };
00426 #endif

Generated on Sun Nov 6 13:35:17 2011 for xrootd by  doxygen 1.3.9.1