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 #include <pthread.h>
00108
00109 class XrdSsiMutex
00110 {
00111 public:
00112
00113 inline bool TryLock() {return pthread_mutex_trylock( &cs ) == 0;}
00114
00115 inline void Lock() {pthread_mutex_lock(&cs);}
00116
00117 inline void UnLock() {pthread_mutex_unlock(&cs);}
00118
00119 enum MutexType {Simple = 0, Recursive = 1};
00120
00121 XrdSsiMutex(MutexType mt=Simple)
00122 {int rc;
00123 if (mt == Simple) rc = pthread_mutex_init(&cs, NULL);
00124 else {pthread_mutexattr_t attr;
00125 if (!(rc = pthread_mutexattr_init(&attr)))
00126 {pthread_mutexattr_settype(&attr,
00127 PTHREAD_MUTEX_RECURSIVE);
00128 rc = pthread_mutex_init(&cs, &attr);
00129 }
00130 }
00131 if (rc) throw Errno2Text(rc);
00132 }
00133
00134 ~XrdSsiMutex() {pthread_mutex_destroy(&cs);}
00135
00136 protected:
00137
00138 pthread_mutex_t cs;
00139
00140 private:
00141 const char* Errno2Text(int ecode);
00142 };
00143
00144
00145
00146
00147
00148 class XrdSsiMutexMon
00149 {
00150 public:
00151
00152 inline void Lock(XrdSsiMutex *mutex)
00153 {if (mtx) {if (mtx != mutex) mtx->UnLock();
00154 else return;
00155 }
00156 mutex->Lock();
00157 mtx = mutex;
00158 };
00159
00160 inline void Lock(XrdSsiMutex &mutex) {Lock(&mutex);}
00161
00162 inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}}
00163
00164 XrdSsiMutexMon(XrdSsiMutex *mutex=0)
00165 {if (mutex) mutex->Lock();
00166 mtx = mutex;
00167 }
00168 XrdSsiMutexMon(XrdSsiMutex &mutex)
00169 {mutex.Lock();
00170 mtx = &mutex;
00171 }
00172
00173 ~XrdSsiMutexMon() {if (mtx) UnLock();}
00174 private:
00175 XrdSsiMutex *mtx;
00176 };
00177 #endif