xrootd
XrdSysPthread.hh
Go to the documentation of this file.
1 #ifndef __SYS_PTHREAD__
2 #define __SYS_PTHREAD__
3 /******************************************************************************/
4 /* */
5 /* X r d S y s P t h r e a d . h h */
6 /* */
7 /* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
8 /* All Rights Reserved. See XrdInfo.cc for complete License Terms */
9 /* Produced by Andrew Hanushevsky for Stanford University under contract */
10 /* DE-AC03-76-SFO0515 with the Department of Energy */
11 /******************************************************************************/
12 
13 #include <errno.h>
14 #ifdef WIN32
15 #define HAVE_STRUCT_TIMESPEC 1
16 #endif
17 #include <pthread.h>
18 #include <signal.h>
19 #ifdef AIX
20 #include <sys/sem.h>
21 #else
22 #include <semaphore.h>
23 #endif
24 
25 #include "XrdSys/XrdSysError.hh"
26 
27 /******************************************************************************/
28 /* X r d S y s C o n d V a r */
29 /******************************************************************************/
30 
31 // XrdSysCondVar implements the standard POSIX-compliant condition variable.
32 // Methods correspond to the equivalent pthread condvar functions.
33 
35 {
36 public:
37 
38 inline void Lock() {pthread_mutex_lock(&cmut);}
39 
40 inline void Signal() {if (relMutex) pthread_mutex_lock(&cmut);
41  pthread_cond_signal(&cvar);
42  if (relMutex) pthread_mutex_unlock(&cmut);
43  }
44 
45 inline void Broadcast() {if (relMutex) pthread_mutex_lock(&cmut);
46  pthread_cond_broadcast(&cvar);
47  if (relMutex) pthread_mutex_unlock(&cmut);
48  }
49 
50 inline void UnLock() {pthread_mutex_unlock(&cmut);}
51 
52  int Wait();
53  int Wait(int sec);
54  int WaitMS(int msec);
55 
56  XrdSysCondVar( int relm=1, // 0->Caller will handle lock/unlock
57  const char *cid=0 // ID string for debugging only
58  ) {pthread_cond_init(&cvar, NULL);
59  pthread_mutex_init(&cmut, NULL);
60  relMutex = relm; condID = (cid ? cid : "unk");
61  }
62  ~XrdSysCondVar() {pthread_cond_destroy(&cvar);
63  pthread_mutex_destroy(&cmut);
64  }
65 private:
66 
67 pthread_cond_t cvar;
68 pthread_mutex_t cmut;
70 const char *condID;
71 };
72 
73 
74 
75 /******************************************************************************/
76 /* X r d S y s C o n d V a r H e l p e r */
77 /******************************************************************************/
78 
79 // XrdSysCondVarHelper is used to implement monitors with the Lock of a a condvar.
80 // Monitors are used to lock
81 // whole regions of code (e.g., a method) and automatically
82 // unlock with exiting the region (e.g., return). The
83 // methods should be self-evident.
84 
86 {
87 public:
88 
89 inline void Lock(XrdSysCondVar *CndVar)
90  {if (cnd) {if (cnd != CndVar) cnd->UnLock();
91  else return;
92  }
93  CndVar->Lock();
94  cnd = CndVar;
95  };
96 
97 inline void UnLock() {if (cnd) {cnd->UnLock(); cnd = 0;}}
98 
100  {if (CndVar) CndVar->Lock();
101  cnd = CndVar;
102  }
104  CndVar.Lock();
105  cnd = &CndVar;
106  }
107 
109 private:
111 };
112 
113 
114 /******************************************************************************/
115 /* X r d S y s M u t e x */
116 /******************************************************************************/
117 
118 // XrdSysMutex implements the standard POSIX mutex. The methods correspond
119 // to the equivalent pthread mutex functions.
120 
122 {
123 public:
124 
125 inline int CondLock()
126  {if (pthread_mutex_trylock( &cs )) return 0;
127  return 1;
128  }
129 
130 inline void Lock() {pthread_mutex_lock(&cs);}
131 
132 inline void UnLock() {pthread_mutex_unlock(&cs);}
133 
134  XrdSysMutex() {pthread_mutex_init(&cs, NULL);}
135  ~XrdSysMutex() {pthread_mutex_destroy(&cs);}
136 
137 protected:
138 
139 pthread_mutex_t cs;
140 };
141 
142 /******************************************************************************/
143 /* X r d S y s R e c M u t e x */
144 /******************************************************************************/
145 
146 // XrdSysRecMutex implements the recursive POSIX mutex. The methods correspond
147 // to the equivalent pthread mutex functions.
148 
150 {
151 public:
152 
154 
155 int InitRecMutex();
156 int ReInitRecMutex();
157 
158 };
159 
160 
161 /******************************************************************************/
162 /* X r d S y s M u t e x H e l p e r */
163 /******************************************************************************/
164 
165 // XrdSysMutexHelper us ised to implement monitors. Monitors are used to lock
166 // whole regions of code (e.g., a method) and automatically
167 // unlock with exiting the region (e.g., return). The
168 // methods should be self-evident.
169 
171 {
172 public:
173 
174 inline void Lock(XrdSysMutex *Mutex)
175  {if (mtx) {if (mtx != Mutex) mtx->UnLock();
176  else return;
177  }
178  Mutex->Lock();
179  mtx = Mutex;
180  };
181 
182 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
183 
185  {if (mutex) mutex->Lock();
186  mtx = mutex;
187  }
189  mutex.Lock();
190  mtx = &mutex;
191  }
192 
194 private:
196 };
197 
198 /******************************************************************************/
199 /* X r d S y s R W L o c k */
200 /******************************************************************************/
201 
202 // XrdSysRWLock implements the standard POSIX wrlock mutex. The methods correspond
203 // to the equivalent pthread wrlock functions.
204 
206 {
207 public:
208 
209 inline int CondReadLock()
210  {if (pthread_rwlock_tryrdlock( &lock )) return 0;
211  return 1;
212  }
213 inline int CondWriteLock()
214  {if (pthread_rwlock_trywrlock( &lock )) return 0;
215  return 1;
216  }
217 
218 inline void ReadLock() {pthread_rwlock_rdlock(&lock);}
219 inline void WriteLock() {pthread_rwlock_wrlock(&lock);}
220 
221 inline void UnLock() {pthread_rwlock_unlock(&lock);}
222 
223  XrdSysRWLock() {pthread_rwlock_init(&lock, NULL);}
224  ~XrdSysRWLock() {pthread_rwlock_destroy(&lock);}
225 
226 protected:
227 
228 pthread_rwlock_t lock;
229 };
230 
231 /******************************************************************************/
232 /* X r d S y s W R L o c k H e l p e r */
233 /******************************************************************************/
234 
235 // XrdSysWRLockHelper : helper class for XrdSysRWLock
236 
238 {
239 public:
240 
241 inline void Lock(XrdSysRWLock *lock, bool rd = 1)
242  {if (lck) {if (lck != lock) lck->UnLock();
243  else return;
244  }
245  if (rd) lock->ReadLock();
246  else lock->WriteLock();
247  lck = lock;
248  };
249 
250 inline void UnLock() {if (lck) {lck->UnLock(); lck = 0;}}
251 
252  XrdSysRWLockHelper(XrdSysRWLock *l=0, bool rd = 1)
253  { if (l) {if (rd) l->ReadLock();
254  else l->WriteLock();
255  }
256  lck = l;
257  }
259  { if (rd) l.ReadLock();
260  else l.WriteLock();
261  lck = &l;
262  }
263 
265 private:
267 };
268 
269 /******************************************************************************/
270 /* X r d S y s S e m a p h o r e */
271 /******************************************************************************/
272 
273 // XrdSysSemaphore implements the classic counting semaphore. The methods
274 // should be self-evident. Note that on certain platforms
275 // semaphores need to be implemented based on condition
276 // variables since no native implementation is available.
277 
278 #ifdef __macos__
279 class XrdSysSemaphore
280 {
281 public:
282 
283  int CondWait();
284 
285  void Post();
286 
287  void Wait();
288 
289  XrdSysSemaphore(int semval=1,const char *cid=0) : semVar(0, cid)
290  {semVal = semval; semWait = 0;}
291  ~XrdSysSemaphore() {}
292 
293 private:
294 
295 XrdSysCondVar semVar;
296 int semVal;
297 int semWait;
298 };
299 
300 #else
301 
303 {
304 public:
305 
306 inline int CondWait()
307  {while(sem_trywait( &h_semaphore ))
308  {if (errno == EAGAIN) return 0;
309  if (errno != EINTR) { throw "sem_CondWait() failed";}
310  }
311  return 1;
312  }
313 
314 inline void Post() {if (sem_post(&h_semaphore))
315  {throw "sem_post() failed";}
316  }
317 
318 inline void Wait() {while (sem_wait(&h_semaphore))
319  {if (EINTR != errno)
320  {throw "sem_wait() failed";}
321  }
322  }
323 
324  XrdSysSemaphore(int semval=1, const char * =0)
325  {if (sem_init(&h_semaphore, 0, semval))
326  {throw "sem_init() failed";}
327  }
328  ~XrdSysSemaphore() {if (sem_destroy(&h_semaphore))
329  {throw "sem_destroy() failed";}
330  }
331 
332 private:
333 
335 };
336 #endif
337 
338 /******************************************************************************/
339 /* X r d S y s T h r e a d */
340 /******************************************************************************/
341 
342 // The C++ standard makes it impossible to link extern "C" methods with C++
343 // methods. Thus, making a full thread object is nearly impossible. So, this
344 // object is used as the thread manager. Since it is static for all intense
345 // and purposes, one does not need to create an instance of it.
346 //
347 
348 // Options to Run()
349 //
350 // BIND creates threads that are bound to a kernel thread.
351 //
352 #define XRDSYSTHREAD_BIND 0x001
353 
354 // HOLD creates a thread that needs to be joined to get its ending value.
355 // Otherwise, a detached thread is created.
356 //
357 #define XRDSYSTHREAD_HOLD 0x002
358 
360 {
361 public:
362 
363 static int Cancel(pthread_t tid) {return pthread_cancel(tid);}
364 
365 static int Detach(pthread_t tid) {return pthread_detach(tid);}
366 
367 
368 static int SetCancelOff() {
369  return pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
370  };
371 
372 static int Join(pthread_t tid, void **ret) {
373  return pthread_join(tid, ret);
374  };
375 
376 static int SetCancelOn() {
377  return pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
378  };
379 
380 static int SetCancelAsynchronous() {
381  return pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
382  };
383 
384 static int SetCancelDeferred() {
385  return pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, 0);
386  };
387 
388 static void CancelPoint() {
389  pthread_testcancel();
390  };
391 
392 
393 static pthread_t ID(void) {return pthread_self();}
394 
395 static int Kill(pthread_t tid) {return pthread_cancel(tid);}
396 
397 static unsigned long Num(void);
398 
399 static int Run(pthread_t *, void *(*proc)(void *), void *arg,
400  int opts=0, const char *desc = 0);
401 
402 static int Same(pthread_t t1, pthread_t t2)
403  {return pthread_equal(t1, t2);}
404 
405 static void setDebug(XrdSysError *erp) {eDest = erp;}
406 
407 static void setStackSize(size_t stsz) {stackSize = stsz;}
408 
409 static int Signal(pthread_t tid, int snum)
410  {return pthread_kill(tid, snum);}
411 
412 static int Wait(pthread_t tid);
413 
416 
417 private:
419 static size_t stackSize;
420 };
421 #endif