00001 #ifndef __SSIATOMICS_HH__
00002 #define __SSIATOMICS_HH__
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 <string.h>
00033
00034 #undef NEED_ATOMIC_MUTEX
00035
00036
00038
00039 #if __cplusplus >= 201103L
00040 #include <atomic>
00041 #define Atomic(type) std::atomic<type>
00042 #define Atomic_IMP "C++11"
00043 #define Atomic_BEG(x)
00044 #define Atomic_DEC(x) x.fetch_sub(1,std::memory_order_relaxed)
00045 #define Atomic_GET(x) x.load(std::memory_order_relaxed)
00046 #define Atomic_GET_STRICT(x) x.load(std::memory_order_acquire)
00047 #define Atomic_INC(x) x.fetch_add(1,std::memory_order_relaxed)
00048 #define Atomic_SET(x,y) x.store(y,std::memory_order_relaxed)
00049 #define Atomic_SET_STRICT(x,y) x.store(y,std::memory_order_release)
00050 #define Atomic_ZAP(x) x.store(0,std::memory_order_relaxed)
00051 #define Atomic_END(x)
00052
00053
00055
00056 #elif __GNUC__ == 4 && __GNUC_MINOR__ > 6
00057 #define Atomic(type) type
00058 #define Atomic_IMP "gnu-atomic"
00059 #define Atomic_BEG(x)
00060 #define Atomic_DEC(x) __atomic_fetch_sub(&x,1,__ATOMIC_RELAXED)
00061 #define Atomic_GET(x) __atomic_load_n (&x, __ATOMIC_RELAXED)
00062 #define Atomic_GET_STRICT(x) __atomic_load_n (&x, __ATOMIC_ACQUIRE)
00063 #define Atomic_INC(x) __atomic_fetch_add(&x,1,__ATOMIC_RELAXED)
00064 #define Atomic_SET(x,y) __atomic_store_n (&x,y,__ATOMIC_RELAXED)
00065 #define Atomic_SET_STRICT(x,y) __atomic_store_n (&x,y,__ATOMIC_RELEASE)
00066 #define Atomic_ZAP(x) __atomic_store_n (&x,0,__ATOMIC_RELAXED)
00067 #define Atomic_END(x)
00068
00069
00073
00074 #elif HAVE_ATOMICS
00075 #define Atomic(type) type
00076 #define Atomic_IMP "gnu-sync"
00077 #define Atomic_BEG(x)
00078 #define Atomic_DEC(x) __sync_fetch_and_sub(&x, 1)
00079 #define Atomic_GET(x) __sync_fetch_and_or (&x, 0)
00080 #define Atomic_GET_STRICT(x) __sync_fetch_and_or (&x, 0)
00081 #define Atomic_INC(x) __sync_fetch_and_add(&x, 1)
00082 #define Atomic_SET(x,y) x=y,__sync_synchronize()
00083 #define Atomic_SET_STRICT(x,y) __sync_synchronize(),x=y,__sync_synchronize()
00084 #define Atomic_ZAP(x) __sync_fetch_and_and(&x, 0)
00085 #define Atomic_END(x)
00086
00087
00089
00090 #else
00091 #define NEED_ATOMIC_MUTEX 1
00092 #define Atomic_IMP "missing"
00093 #define Atomic(type) type
00094 #define Atomic_BEG(x) pthread_mutex_lock(x)
00095 #define Atomic_DEC(x) x--
00096 #define Atomic_GET(x) x
00097 #define Atomic_INC(x) x++
00098 #define Atomic_SET(x,y) x = y
00099 #define Atomic_ZAP(x) x = 0
00100 #define Atomic_END(x) pthread_mutex_unlock(x)
00101 #endif
00102
00103
00104
00105
00106
00107
00108 #include <pthread.h>
00109
00110 class XrdSsiMutex
00111 {
00112 public:
00113
00114 inline bool TryLock() {return pthread_mutex_trylock( &cs ) == 0;}
00115
00116 inline void Lock() {pthread_mutex_lock(&cs);}
00117
00118 inline void UnLock() {pthread_mutex_unlock(&cs);}
00119
00120 enum MutexType {Simple = 0, Recursive = 1};
00121
00122 XrdSsiMutex(MutexType mt=Simple)
00123 {int rc;
00124 if (mt == Simple) rc = pthread_mutex_init(&cs, NULL);
00125 else {pthread_mutexattr_t attr;
00126 if (!(rc = pthread_mutexattr_init(&attr)))
00127 {pthread_mutexattr_settype(&attr,
00128 PTHREAD_MUTEX_RECURSIVE);
00129 rc = pthread_mutex_init(&cs, &attr);
00130 }
00131 }
00132 if (rc) throw strerror(rc);
00133 }
00134
00135 ~XrdSsiMutex() {pthread_mutex_destroy(&cs);}
00136
00137 protected:
00138
00139 pthread_mutex_t cs;
00140 };
00141
00142
00143
00144
00145
00146 class XrdSsiMutexMon
00147 {
00148 public:
00149
00150 inline void Lock(XrdSsiMutex *mutex)
00151 {if (mtx) {if (mtx != mutex) mtx->UnLock();
00152 else return;
00153 }
00154 mutex->Lock();
00155 mtx = mutex;
00156 };
00157
00158 inline void Lock(XrdSsiMutex &mutex) {Lock(&mutex);}
00159
00160 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
00161
00162 XrdSsiMutexMon(XrdSsiMutex *mutex=0)
00163 {if (mutex) mutex->Lock();
00164 mtx = mutex;
00165 }
00166 XrdSsiMutexMon(XrdSsiMutex &mutex)
00167 {mutex.Lock();
00168 mtx = &mutex;
00169 }
00170
00171 ~XrdSsiMutexMon() {if (mtx) UnLock();}
00172 private:
00173 XrdSsiMutex *mtx;
00174 };
00175 #endif