XRootD
XrdSsiAtomics.hh
Go to the documentation of this file.
1 #ifndef __SSIATOMICS_HH__
2 #define __SSIATOMICS_HH__
3 /******************************************************************************/
4 /* */
5 /* X r d S s i A t o m i c s . h h */
6 /* */
7 /* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
8 /* Produced by Andrew Hanushevsky for Stanford University under contract */
9 /* DE-AC02-76-SFO0515 with the Department of Energy */
10 /* */
11 /* This file is part of the XRootD software suite. */
12 /* */
13 /* XRootD is free software: you can redistribute it and/or modify it under */
14 /* the terms of the GNU Lesser General Public License as published by the */
15 /* Free Software Foundation, either version 3 of the License, or (at your */
16 /* option) any later version. */
17 /* */
18 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
19 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
20 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
21 /* License for more details. */
22 /* */
23 /* You should have received a copy of the GNU Lesser General Public License */
24 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
25 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
26 /* */
27 /* The copyright holder's institutional names and contributor's names may not */
28 /* be used to endorse or promote products derived from this software without */
29 /* specific prior written permission of the institution or contributor. */
30 /******************************************************************************/
31 
32 #include <cstring>
33 
34 #undef NEED_ATOMIC_MUTEX
35 
36 //-----------------------------------------------------------------------------
38 //-----------------------------------------------------------------------------
39 #if __cplusplus >= 201103L
40 #include <atomic>
41 #define Atomic(type) std::atomic<type>
42 #define Atomic_IMP "C++11"
43 #define Atomic_BEG(x)
44 #define Atomic_DEC(x) x.fetch_sub(1,std::memory_order_relaxed)
45 #define Atomic_GET(x) x.load(std::memory_order_relaxed)
46 #define Atomic_GET_STRICT(x) x.load(std::memory_order_acquire)
47 #define Atomic_INC(x) x.fetch_add(1,std::memory_order_relaxed)
48 #define Atomic_SET(x,y) x.store(y,std::memory_order_relaxed)
49 #define Atomic_SET_STRICT(x,y) x.store(y,std::memory_order_release)
50 #define Atomic_ZAP(x) x.store(0,std::memory_order_relaxed)
51 #define Atomic_END(x)
52 
53 //-----------------------------------------------------------------------------
55 //-----------------------------------------------------------------------------
56 #elif __GNUC__ == 4 && __GNUC_MINOR__ > 6
57 #define Atomic(type) type
58 #define Atomic_IMP "gnu-atomic"
59 #define Atomic_BEG(x)
60 #define Atomic_DEC(x) __atomic_fetch_sub(&x,1,__ATOMIC_RELAXED)
61 #define Atomic_GET(x) __atomic_load_n (&x, __ATOMIC_RELAXED)
62 #define Atomic_GET_STRICT(x) __atomic_load_n (&x, __ATOMIC_ACQUIRE)
63 #define Atomic_INC(x) __atomic_fetch_add(&x,1,__ATOMIC_RELAXED)
64 #define Atomic_SET(x,y) __atomic_store_n (&x,y,__ATOMIC_RELAXED)
65 #define Atomic_SET_STRICT(x,y) __atomic_store_n (&x,y,__ATOMIC_RELEASE)
66 #define Atomic_ZAP(x) __atomic_store_n (&x,0,__ATOMIC_RELAXED)
67 #define Atomic_END(x)
68 
69 //-----------------------------------------------------------------------------
73 //-----------------------------------------------------------------------------
74 #elif HAVE_ATOMICS
75 #define Atomic(type) type
76 #define Atomic_IMP "gnu-sync"
77 #define Atomic_BEG(x)
78 #define Atomic_DEC(x) __sync_fetch_and_sub(&x, 1)
79 #define Atomic_GET(x) __sync_fetch_and_or (&x, 0)
80 #define Atomic_GET_STRICT(x) __sync_fetch_and_or (&x, 0)
81 #define Atomic_INC(x) __sync_fetch_and_add(&x, 1)
82 #define Atomic_SET(x,y) x=y,__sync_synchronize()
83 #define Atomic_SET_STRICT(x,y) __sync_synchronize(),x=y,__sync_synchronize()
84 #define Atomic_ZAP(x) __sync_fetch_and_and(&x, 0)
85 #define Atomic_END(x)
86 
87 //-----------------------------------------------------------------------------
89 //-----------------------------------------------------------------------------
90 #else
91 #define NEED_ATOMIC_MUTEX 1
92 #define Atomic_IMP "missing"
93 #define Atomic(type) type
94 #define Atomic_BEG(x) pthread_mutex_lock(x)
95 #define Atomic_DEC(x) x--
96 #define Atomic_GET(x) x
97 #define Atomic_INC(x) x++
98 #define Atomic_SET(x,y) x = y
99 #define Atomic_ZAP(x) x = 0
100 #define Atomic_END(x) pthread_mutex_unlock(x)
101 #endif
102 
103 /******************************************************************************/
104 /* X r d S s i M u t e x */
105 /******************************************************************************/
106 
107 #include <pthread.h>
108 
110 {
111 public:
112 
113 inline bool TryLock() {return pthread_mutex_trylock( &cs ) == 0;}
114 
115 inline void Lock() {pthread_mutex_lock(&cs);}
116 
117 inline void UnLock() {pthread_mutex_unlock(&cs);}
118 
119 enum MutexType {Simple = 0, Recursive = 1};
120 
122  {int rc;
123  if (mt == Simple) rc = pthread_mutex_init(&cs, NULL);
124  else {pthread_mutexattr_t attr;
125  if (!(rc = pthread_mutexattr_init(&attr)))
126  {pthread_mutexattr_settype(&attr,
127  PTHREAD_MUTEX_RECURSIVE);
128  rc = pthread_mutex_init(&cs, &attr);
129  }
130  }
131  if (rc) throw Errno2Text(rc);
132  }
133 
134  ~XrdSsiMutex() {pthread_mutex_destroy(&cs);}
135 
136 protected:
137 
138 pthread_mutex_t cs;
139 
140 private:
141 const char* Errno2Text(int ecode);
142 };
143 
144 /******************************************************************************/
145 /* X r d S s i M u t e x M o n */
146 /******************************************************************************/
147 
149 {
150 public:
151 
152 inline void Lock(XrdSsiMutex *mutex)
153  {if (mtx) {if (mtx != mutex) mtx->UnLock();
154  else return;
155  }
156  mutex->Lock();
157  mtx = mutex;
158  };
159 
160 inline void Lock(XrdSsiMutex &mutex) {Lock(&mutex);}
161 
162 inline void Reset() {mtx = 0;}
163 
164 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
165 
167  {if (mutex) mutex->Lock();
168  mtx = mutex;
169  }
171  {mutex.Lock();
172  mtx = &mutex;
173  }
174 
175  ~XrdSsiMutexMon() {if (mtx) UnLock();}
176 private:
177 XrdSsiMutex *mtx;
178 };
179 #endif
XrdSsiMutexMon(XrdSsiMutex &mutex)
void Lock(XrdSsiMutex &mutex)
XrdSsiMutexMon(XrdSsiMutex *mutex=0)
void Lock(XrdSsiMutex *mutex)
XrdSsiMutex(MutexType mt=Simple)
pthread_mutex_t cs