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