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 namespace eq
00022 {
00023 namespace base
00024 {
00025 #if defined(__GNUC__) && ( (__GNUC__ > 4) || ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)) )
00026
00028 template <typename T>
00029 class Atomic: public NonCopyable
00030 {
00031 public:
00033 explicit Atomic( T v = 0 )
00034 : _value(v)
00035 {}
00036
00038 operator T(void) const
00039 {
00040 return __sync_fetch_and_add(&_value, 0);
00041 }
00042
00044 void operator =(T v)
00045 {
00046 _value = v;
00047 __sync_synchronize();
00048 }
00049
00051 T operator +=(T v)
00052 {
00053 return __sync_add_and_fetch(&_value, v);
00054 }
00055
00057 T operator -=(T v)
00058 {
00059 return __sync_sub_and_fetch(&_value, v);
00060 }
00061
00063 T operator ++(void)
00064 {
00065 return __sync_add_and_fetch(&_value, 1);
00066 }
00067
00069 T operator --(void)
00070 {
00071 return __sync_sub_and_fetch(&_value, 1);
00072 }
00073
00075 T operator ++(int)
00076 {
00077 return __sync_fetch_and_add(&_value, 1);
00078 }
00079
00081 T operator --(int)
00082 {
00083 return __sync_fetch_and_sub(&_value, 1);
00084 }
00085
00086 private:
00087 mutable T _value;
00088 };
00089
00090 #elif defined(__GLIBCPP__) || defined(__GLIBCXX__)
00091
00092 template <typename T>
00093 class Atomic: public NonCopyable
00094 {
00095 public:
00096 explicit Atomic(T v = 0)
00097 : _value(v)
00098 {}
00099
00100 operator T(void) const
00101 {
00102 return __gnu_cxx::__exchange_and_add(&_value, 0);
00103 }
00104
00105 void operator =(T v)
00106 {
00107 _value = v;
00108 }
00109
00110 T operator +=(T v)
00111 {
00112 return __gnu_cxx::__exchange_and_add(&_value, v) + v;
00113 }
00114
00115 T operator -=(T v)
00116 {
00117 return __gnu_cxx::__exchange_and_add(&_value, -v) - v;
00118 }
00119
00120
00121 T operator ++(void)
00122 {
00123 return operator+=(1);
00124 }
00125
00126
00127 T operator --(void)
00128 {
00129 return operator-=(1);
00130 }
00131
00132
00133 T operator ++(int)
00134 {
00135 return __gnu_cxx::__exchange_and_add(&_value, 1);
00136 }
00137
00138
00139 T operator --(int)
00140 {
00141 return __gnu_cxx::__exchange_and_add(&_value, -1);
00142 }
00143
00144 private:
00145 mutable _Atomic_word _value;
00146 };
00147
00148 #elif defined (EQ_HAS_COMPARE_AND_SWAP)
00149
00150 template <typename T>
00151 class Atomic: public NonCopyable
00152 {
00153 public:
00154 explicit Atomic(T v = 0)
00155 {
00156 *this = v;
00157 }
00158
00159 operator T(void) const
00160 {
00161 memoryBarrier();
00162 return _value;
00163 }
00164
00165 void operator =(T v)
00166 {
00167 _value = v;
00168 memoryBarrier();
00169 }
00170
00171
00172 T operator ++()
00173 {
00174 return *this += 1;
00175 }
00176
00177
00178 T operator --()
00179 {
00180 return *this -= 1;
00181 }
00182
00183 T operator +=(T v)
00184 {
00185 for(;;)
00186 {
00187 T oldv = _value;
00188 T newv = oldv+v;
00189 if(compareAndSwap(&_value,oldv,newv))
00190 return newv;
00191 }
00192 }
00193
00194 T operator -=(T v)
00195 {
00196 for(;;)
00197 {
00198 T oldv = _value;
00199 T newv = oldv-v;
00200 if(compareAndSwap(&_value,oldv,newv))
00201 return newv;
00202 }
00203 }
00204
00205
00206 T operator ++(int)
00207 {
00208 for(;;)
00209 {
00210 T oldv = _value;
00211 if(compareAndSwap(&_value,oldv,oldv+1))
00212 return oldv;
00213 }
00214 }
00215
00216
00217 T operator --(int)
00218 {
00219 for(;;)
00220 {
00221 T oldv = _value;
00222 if(compareAndSwap(&_value,oldv,oldv-1))
00223 return oldv;
00224 }
00225 }
00226
00227 private:
00228 T _value;
00229 };
00230
00231 #else
00232 # warning ("Atomic emulation")
00233 # include <eq/base/lock.h>
00234
00235 template <typename T>
00236 class Atomic: public NonCopyable
00237 {
00238 public:
00239 explicit Atomic(T v = 0)
00240 {
00241 *this = v;
00242 }
00243
00244 operator T(void) const
00245 {
00246 return _value;
00247 }
00248
00249 void operator =(T v)
00250 {
00251 _lock.set();
00252 _value = v;
00253 _lock.unset();
00254 }
00255
00256
00257 T operator ++()
00258 {
00259 return *this += 1;
00260 }
00261
00262
00263 T operator --()
00264 {
00265 return *this -= 1;
00266 }
00267
00268 T operator +=(T v)
00269 {
00270 _lock.set();
00271 _value += v;
00272 T newv = _value;
00273 _lock.unset();
00274
00275 return newv;
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
00289 T operator ++(int)
00290 {
00291 _lock.set();
00292 T oldv = _value;
00293 ++_value;
00294 _lock.unset();
00295
00296 return oldv;
00297 }
00298
00299
00300 T operator --(int)
00301 {
00302 _lock.set();
00303 T oldv = _value;
00304 --_value;
00305 _lock.unset();
00306
00307 return oldv;
00308 }
00309
00310 private:
00311 T _value;
00312 Lock _lock;
00313 };
00314 #endif
00315
00316 typedef Atomic< long > mtLong;
00317 }
00318
00319 }
00320 #endif // EQBASE_ATOMIC_H