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 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     /* prefix operator */
00121     T operator ++(void)
00122     {
00123         return operator+=(1);
00124     }
00125 
00126     /* prefix operator */
00127     T operator --(void)
00128     {
00129         return operator-=(1);
00130     }
00131 
00132     /* postfix operator */
00133     T operator ++(int)
00134     {
00135         return __gnu_cxx::__exchange_and_add(&_value, 1);
00136     }
00137 
00138     /* postfix operator */
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) /* emulate via compareAndSwap */
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     /* prefix operator */
00172     T operator ++()
00173     {
00174         return *this += 1;
00175     }
00176 
00177     /* prefix operator */
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     /* postfix operator */
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     /* postfix operator */
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>       // used in inline methods
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     /* prefix operator */
00257     T operator ++()
00258     {
00259         return *this += 1;
00260     }
00261 
00262     /* prefix operator */
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     /* postfix operator */
00289     T operator ++(int)
00290     {
00291         _lock.set();
00292         T oldv = _value;
00293         ++_value;
00294         _lock.unset();
00295         
00296         return oldv;
00297     }
00298 
00299     /* postfix operator */
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
Generated on Mon Aug 10 18:58:31 2009 for Equalizer 0.9 by  doxygen 1.5.8