atomic.h
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifndef EQBASE_ATOMIC_H
00016 #define EQBASE_ATOMIC_H
00017
00018 #include <eq/base/nonCopyable.h>
00019 #include <eq/base/compareAndSwap.h>
00020
00021 #include <string>
00022
00023 namespace eq
00024 {
00025 namespace base
00026 {
00027 #ifdef EQ_GCC_4_1_OR_LATER
00028
00038 template <typename T>
00039 class Atomic: public NonCopyable
00040 {
00041 public:
00043 explicit Atomic( T v = 0 )
00044 : _value(v)
00045 {}
00046
00048 operator T(void) const
00049 {
00050 return __sync_fetch_and_add(&_value, 0);
00051 }
00052
00054 void operator =(T v)
00055 {
00056 _value = v;
00057 __sync_synchronize();
00058 }
00059
00061 T operator +=(T v)
00062 {
00063 return __sync_add_and_fetch(&_value, v);
00064 }
00065
00067 T operator -=(T v)
00068 {
00069 return __sync_sub_and_fetch(&_value, v);
00070 }
00071
00073 T operator ++(void)
00074 {
00075 return __sync_add_and_fetch(&_value, 1);
00076 }
00077
00079 T operator --(void)
00080 {
00081 return __sync_sub_and_fetch(&_value, 1);
00082 }
00083
00085 T operator ++(int)
00086 {
00087 return __sync_fetch_and_add(&_value, 1);
00088 }
00089
00091 T operator --(int)
00092 {
00093 return __sync_fetch_and_sub(&_value, 1);
00094 }
00095
00096 private:
00097 mutable T _value;
00098 };
00099
00100 #elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
00101
00102 template <typename T>
00103 class Atomic: public NonCopyable
00104 {
00105 public:
00106 explicit Atomic(T v = 0)
00107 : _value(v)
00108 {}
00109
00110 operator T(void) const
00111 {
00112 return __gnu_cxx::__exchange_and_add(&_value, 0);
00113 }
00114
00115 void operator =(T v)
00116 {
00117 _value = v;
00118 }
00119
00120 T operator +=(T v)
00121 {
00122 return __gnu_cxx::__exchange_and_add(&_value, v) + v;
00123 }
00124
00125 T operator -=(T v)
00126 {
00127 return __gnu_cxx::__exchange_and_add(&_value, -v) - v;
00128 }
00129
00130
00131 T operator ++(void)
00132 {
00133 return operator+=(1);
00134 }
00135
00136
00137 T operator --(void)
00138 {
00139 return operator-=(1);
00140 }
00141
00142
00143 T operator ++(int)
00144 {
00145 return __gnu_cxx::__exchange_and_add(&_value, 1);
00146 }
00147
00148
00149 T operator --(int)
00150 {
00151 return __gnu_cxx::__exchange_and_add(&_value, -1);
00152 }
00153
00154 private:
00155 mutable _Atomic_word _value;
00156 };
00157
00158 #elif defined (EQ_HAS_COMPARE_AND_SWAP)
00159
00160 template <typename T>
00161 class Atomic: public NonCopyable
00162 {
00163 public:
00164 explicit Atomic(T v = 0)
00165 {
00166 *this = v;
00167 }
00168
00169 operator T(void) const
00170 {
00171 memoryBarrier();
00172 return _value;
00173 }
00174
00175 void operator =(T v)
00176 {
00177 _value = v;
00178 memoryBarrier();
00179 }
00180
00181
00182 T operator ++()
00183 {
00184 return *this += 1;
00185 }
00186
00187
00188 T operator --()
00189 {
00190 return *this -= 1;
00191 }
00192
00193 T operator +=(T v)
00194 {
00195 for(;;)
00196 {
00197 T oldv = _value;
00198 T newv = oldv+v;
00199 if(compareAndSwap(&_value,oldv,newv))
00200 return newv;
00201 }
00202 }
00203
00204 T operator -=(T v)
00205 {
00206 for(;;)
00207 {
00208 T oldv = _value;
00209 T newv = oldv-v;
00210 if(compareAndSwap(&_value,oldv,newv))
00211 return newv;
00212 }
00213 }
00214
00215
00216 T operator ++(int)
00217 {
00218 for(;;)
00219 {
00220 T oldv = _value;
00221 if(compareAndSwap(&_value,oldv,oldv+1))
00222 return oldv;
00223 }
00224 }
00225
00226
00227 T operator --(int)
00228 {
00229 for(;;)
00230 {
00231 T oldv = _value;
00232 if(compareAndSwap(&_value,oldv,oldv-1))
00233 return oldv;
00234 }
00235 }
00236
00237 private:
00238 T _value;
00239 };
00240
00241 #else
00242 # warning ("Atomic emulation")
00243 # include <eq/base/lock.h>
00244
00245 template <typename T>
00246 class Atomic: public NonCopyable
00247 {
00248 public:
00249 explicit Atomic(T v = 0)
00250 {
00251 *this = v;
00252 }
00253
00254 operator T(void) const
00255 {
00256 return _value;
00257 }
00258
00259 void operator =(T v)
00260 {
00261 _lock.set();
00262 _value = v;
00263 _lock.unset();
00264 }
00265
00266
00267 T operator ++()
00268 {
00269 return *this += 1;
00270 }
00271
00272
00273 T operator --()
00274 {
00275 return *this -= 1;
00276 }
00277
00278 T operator +=(T v)
00279 {
00280 _lock.set();
00281 _value += v;
00282 T newv = _value;
00283 _lock.unset();
00284
00285 return newv;
00286 }
00287
00288 T operator -=(T v)
00289 {
00290 _lock.set();
00291 _value -= v;
00292 T newv = _value;
00293 _lock.unset();
00294
00295 return newv;
00296 }
00297
00298
00299 T operator ++(int)
00300 {
00301 _lock.set();
00302 T oldv = _value;
00303 ++_value;
00304 _lock.unset();
00305
00306 return oldv;
00307 }
00308
00309
00310 T operator --(int)
00311 {
00312 _lock.set();
00313 T oldv = _value;
00314 --_value;
00315 _lock.unset();
00316
00317 return oldv;
00318 }
00319
00320 private:
00321 T _value;
00322 Lock _lock;
00323 };
00324 #endif
00325
00326 typedef Atomic< long > a_int32_t;
00327 }
00328
00329 }
00330 #endif // EQBASE_ATOMIC_H