Equalizer 1.0

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-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
Generated on Sun May 8 2011 19:11:04 for Equalizer 1.0 by  doxygen 1.7.3