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