atomic.h

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-2009, Stefan Eilemann <eile@equalizergraphics.com> 
00011    Modifications to use within eq::base namespace and naming conventions.
00012    Original at http://tim.klingt.org/git?p=boost_lockfree.git;a=tree
00013 */
00014 
00015 #ifndef EQBASE_ATOMIC_H
00016 #define EQBASE_ATOMIC_H
00017 
00018 #include <eq/base/nonCopyable.h>    // base class
00019 #include <eq/base/compareAndSwap.h> // used in inline methods
00020 
00021 #include <string> // _Atomic_word
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     /* prefix operator */
00131     T operator ++(void)
00132     {
00133         return operator+=(1);
00134     }
00135 
00136     /* prefix operator */
00137     T operator --(void)
00138     {
00139         return operator-=(1);
00140     }
00141 
00142     /* postfix operator */
00143     T operator ++(int)
00144     {
00145         return __gnu_cxx::__exchange_and_add(&_value, 1);
00146     }
00147 
00148     /* postfix operator */
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) /* emulate via compareAndSwap */
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     /* prefix operator */
00182     T operator ++()
00183     {
00184         return *this += 1;
00185     }
00186 
00187     /* prefix operator */
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     /* postfix operator */
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     /* postfix operator */
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>       // used in inline methods
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     /* prefix operator */
00267     T operator ++()
00268     {
00269         return *this += 1;
00270     }
00271 
00272     /* prefix operator */
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     /* postfix operator */
00299     T operator ++(int)
00300     {
00301         _lock.set();
00302         T oldv = _value;
00303         ++_value;
00304         _lock.unset();
00305         
00306         return oldv;
00307     }
00308 
00309     /* postfix operator */
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
Generated on Sat Feb 6 12:59:41 2010 for Equalizer 0.9.1 by  doxygen 1.6.1