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 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00009 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00010 /*                                                                            */
00011 /* This file is part of the XRootD software suite.                            */
00012 /*                                                                            */
00013 /* XRootD is free software: you can redistribute it and/or modify it under    */
00014 /* the terms of the GNU Lesser General Public License as published by the     */
00015 /* Free Software Foundation, either version 3 of the License, or (at your     */
00016 /* option) any later version.                                                 */
00017 /*                                                                            */
00018 /* XRootD is distributed in the hope that it will be useful, but WITHOUT      */
00019 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      */
00020 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public       */
00021 /* License for more details.                                                  */
00022 /*                                                                            */
00023 /* You should have received a copy of the GNU Lesser General Public License   */
00024 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file  */
00025 /* COPYING (GPL license).  If not, see <http://www.gnu.org/licenses/>.        */
00026 /*                                                                            */
00027 /* The copyright holder's institutional names and contributor's names may not */
00028 /* be used to endorse or promote products derived from this software without  */
00029 /* specific prior written permission of the institution or contributor.       */
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 /*                         X r d S y s C o n d V a r                          */
00048 /******************************************************************************/
00049   
00050 // XrdSysCondVar implements the standard POSIX-compliant condition variable.
00051 //               Methods correspond to the equivalent pthread condvar functions.
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, // 0->Caller will handle lock/unlock
00076                     const char *cid=0   // ID string for debugging only
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 /*                     X r d S y s C o n d V a r H e l p e r                  */
00096 /******************************************************************************/
00097 
00098 // XrdSysCondVarHelper is used to implement monitors with the Lock of a a condvar.
00099 //                     Monitors are used to lock
00100 //                     whole regions of code (e.g., a method) and automatically
00101 //                     unlock with exiting the region (e.g., return). The
00102 //                     methods should be self-evident.
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 /*                           X r d S y s M u t e x                            */
00135 /******************************************************************************/
00136 
00137 // XrdSysMutex implements the standard POSIX mutex. The methods correspond
00138 //             to the equivalent pthread mutex functions.
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 
00149 inline void   Lock() {pthread_mutex_lock(&cs);}
00150 
00151 inline void UnLock() {pthread_mutex_unlock(&cs);}
00152 
00153         XrdSysMutex() {pthread_mutex_init(&cs, NULL);}
00154        ~XrdSysMutex() {pthread_mutex_destroy(&cs);}
00155 
00156 protected:
00157 
00158 pthread_mutex_t cs;
00159 };
00160 
00161 /******************************************************************************/
00162 /*                         X r d S y s R e c M u t e x                        */
00163 /******************************************************************************/
00164 
00165 // XrdSysRecMutex implements the recursive POSIX mutex. The methods correspond
00166 //             to the equivalent pthread mutex functions.
00167   
00168 class XrdSysRecMutex: public XrdSysMutex
00169 {
00170 public:
00171 
00172 XrdSysRecMutex();
00173 
00174 int InitRecMutex();
00175 int ReInitRecMutex();
00176 
00177 };
00178 
00179 
00180 /******************************************************************************/
00181 /*                     X r d S y s M u t e x H e l p e r                      */
00182 /******************************************************************************/
00183 
00184 // XrdSysMutexHelper us ised to implement monitors. Monitors are used to lock
00185 //                   whole regions of code (e.g., a method) and automatically
00186 //                   unlock with exiting the region (e.g., return). The
00187 //                   methods should be self-evident.
00188   
00189 class XrdSysMutexHelper
00190 {
00191 public:
00192 
00193 inline void   Lock(XrdSysMutex *Mutex)
00194                   {if (mtx) {if (mtx != Mutex) mtx->UnLock();
00195                                 else return;
00196                             }
00197                    Mutex->Lock();
00198                    mtx = Mutex;
00199                   };
00200 
00201 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
00202 
00203             XrdSysMutexHelper(XrdSysMutex *mutex=0)
00204                  {if (mutex) mutex->Lock();
00205                   mtx = mutex;
00206                  }
00207             XrdSysMutexHelper(XrdSysMutex &mutex) {
00208                  mutex.Lock();
00209                  mtx = &mutex;
00210                  }
00211 
00212            ~XrdSysMutexHelper() {if (mtx) UnLock();}
00213 private:
00214 XrdSysMutex *mtx;
00215 };
00216 
00217 /******************************************************************************/
00218 /*                           X r d S y s R W L o c k                          */
00219 /******************************************************************************/
00220 
00221 // XrdSysRWLock implements the standard POSIX wrlock mutex. The methods correspond
00222 //             to the equivalent pthread wrlock functions.
00223   
00224 class XrdSysRWLock
00225 {
00226 public:
00227 
00228 inline int CondReadLock()
00229        {if (pthread_rwlock_tryrdlock( &lock )) return 0;
00230         return 1;
00231        }
00232 inline int CondWriteLock()
00233        {if (pthread_rwlock_trywrlock( &lock )) return 0;
00234         return 1;
00235        }
00236 
00237 inline void  ReadLock() {pthread_rwlock_rdlock(&lock);}
00238 inline void  WriteLock() {pthread_rwlock_wrlock(&lock);}
00239 
00240 inline void UnLock() {pthread_rwlock_unlock(&lock);}
00241 
00242         XrdSysRWLock() {pthread_rwlock_init(&lock, NULL);}
00243        ~XrdSysRWLock() {pthread_rwlock_destroy(&lock);}
00244 
00245 inline void ReInitialize()
00246 {
00247   pthread_rwlock_destroy(&lock);
00248   pthread_rwlock_init(&lock, NULL);
00249 }
00250 
00251 protected:
00252 
00253 pthread_rwlock_t lock;
00254 };
00255 
00256 /******************************************************************************/
00257 /*                     X r d S y s W R L o c k H e l p e r                    */
00258 /******************************************************************************/
00259 
00260 // XrdSysWRLockHelper : helper class for XrdSysRWLock
00261   
00262 class XrdSysRWLockHelper
00263 {
00264 public:
00265 
00266 inline void   Lock(XrdSysRWLock *lock, bool rd = 1)
00267                   {if (lck) {if (lck != lock) lck->UnLock();
00268                                 else return;
00269                             }
00270                    if (rd) lock->ReadLock();
00271                       else lock->WriteLock();
00272                    lck = lock;
00273                   };
00274 
00275 inline void UnLock() {if (lck) {lck->UnLock(); lck = 0;}}
00276 
00277             XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd = 1)
00278                  { if (l) {if (rd) l->ReadLock();
00279                               else l->WriteLock();
00280                           }
00281                    lck = l;
00282                  }
00283             XrdSysRWLockHelper(XrdSysRWLock &l, bool rd = 1)
00284                  { if (rd) l.ReadLock();
00285                       else l.WriteLock();
00286                    lck = &l;
00287                  }
00288 
00289            ~XrdSysRWLockHelper() {if (lck) UnLock();}
00290 private:
00291 XrdSysRWLock *lck;
00292 };
00293 
00294 /******************************************************************************/
00295 /*                       X r d S y s S e m a p h o r e                        */
00296 /******************************************************************************/
00297 
00298 // XrdSysSemaphore implements the classic counting semaphore. The methods
00299 //                 should be self-evident. Note that on certain platforms
00300 //                 semaphores need to be implemented based on condition
00301 //                 variables since no native implementation is available.
00302   
00303 #ifdef __APPLE__
00304 class XrdSysSemaphore
00305 {
00306 public:
00307 
00308        int  CondWait();
00309 
00310        void Post();
00311 
00312        void Wait();
00313 
00314 static void CleanUp(void *semVar);
00315 
00316   XrdSysSemaphore(int semval=1,const char *cid=0) : semVar(0, cid)
00317                                   {semVal = semval; semWait = 0;}
00318  ~XrdSysSemaphore() {}
00319 
00320 private:
00321 
00322 XrdSysCondVar semVar;
00323 int           semVal;
00324 int           semWait;
00325 };
00326 
00327 #else
00328 
00329 class XrdSysSemaphore
00330 {
00331 public:
00332 
00333 inline int  CondWait()
00334        {while(sem_trywait( &h_semaphore ))
00335              {if (errno == EAGAIN) return 0;
00336               if (errno != EINTR) { throw "sem_CondWait() failed";}
00337              }
00338         return 1;
00339        }
00340 
00341 inline void Post() {if (sem_post(&h_semaphore))
00342                        {throw "sem_post() failed";}
00343                    }
00344 
00345 inline void Wait() {while (sem_wait(&h_semaphore))
00346                           {if (EINTR != errno) 
00347                               {throw "sem_wait() failed";}
00348                           }
00349                    }
00350 
00351   XrdSysSemaphore(int semval=1, const char * =0)
00352                                {if (sem_init(&h_semaphore, 0, semval))
00353                                    {throw "sem_init() failed";}
00354                                }
00355  ~XrdSysSemaphore() {if (sem_destroy(&h_semaphore))
00356                        {throw "sem_destroy() failed";}
00357                    }
00358 
00359 private:
00360 
00361 sem_t h_semaphore;
00362 };
00363 #endif
00364 
00365 /******************************************************************************/
00366 /*                          X r d S y s T h r e a d                           */
00367 /******************************************************************************/
00368   
00369 // The C++ standard makes it impossible to link extern "C" methods with C++
00370 // methods. Thus, making a full thread object is nearly impossible. So, this
00371 // object is used as the thread manager. Since it is static for all intense
00372 // and purposes, one does not need to create an instance of it.
00373 //
00374 
00375 // Options to Run()
00376 //
00377 // BIND creates threads that are bound to a kernel thread.
00378 //
00379 #define XRDSYSTHREAD_BIND 0x001
00380 
00381 // HOLD creates a thread that needs to be joined to get its ending value.
00382 //      Otherwise, a detached thread is created.
00383 //
00384 #define XRDSYSTHREAD_HOLD 0x002
00385 
00386 class XrdSysThread
00387 {
00388 public:
00389 
00390 static int          Cancel(pthread_t tid) {return pthread_cancel(tid);}
00391 
00392 static int          Detach(pthread_t tid) {return pthread_detach(tid);}
00393 
00394 
00395 static  int  SetCancelOff() {
00396       return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
00397  };
00398 
00399 static  int  Join(pthread_t tid, void **ret) {
00400    return pthread_join(tid, ret);
00401  };
00402 
00403 static  int  SetCancelOn() {
00404       return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
00405  };
00406 
00407 static  int  SetCancelAsynchronous() {
00408       return pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
00409  };
00410 
00411 static int  SetCancelDeferred() {
00412       return pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
00413  };
00414 
00415 static void  CancelPoint() {
00416       pthread_testcancel();
00417  };
00418 
00419 
00420 static pthread_t    ID(void)              {return pthread_self();}
00421 
00422 static int          Kill(pthread_t tid)   {return pthread_cancel(tid);}
00423 
00424 static unsigned long Num(void);
00425 
00426 static int          Run(pthread_t *, void *(*proc)(void *), void *arg, 
00427                         int opts=0, const char *desc = 0);
00428 
00429 static int          Same(pthread_t t1, pthread_t t2)
00430                         {return pthread_equal(t1, t2);}
00431 
00432 static void         setDebug(XrdSysError *erp) {eDest = erp;}
00433 
00434 static void         setStackSize(size_t stsz) {stackSize = stsz;}
00435 
00436 static int          Signal(pthread_t tid, int snum)
00437                        {return pthread_kill(tid, snum);}
00438  
00439 static int          Wait(pthread_t tid);
00440 
00441                     XrdSysThread() {}
00442                    ~XrdSysThread() {}
00443 
00444 private:
00445 static XrdSysError  *eDest;
00446 static size_t        stackSize;
00447 };
00448 #endif

Generated on 16 Jan 2014 for xrootd by  doxygen 1.4.7