Equalizer  1.2.1
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/api.h>
00019 #include <co/base/nonCopyable.h>    // base class
00020 #include <co/base/compiler.h>       // GCC version
00021 #include <co/base/types.h>
00022 
00023 #ifdef _MSC_VER
00024 #  pragma warning (push)
00025 #  pragma warning (disable: 4985) // inconsistent decl of ceil
00026 #    include <math.h> // include math.h early to avoid warning later
00027 #    include <intrin.h>
00028 #  pragma warning (pop)
00029 #  pragma intrinsic(_ReadWriteBarrier)
00030 #endif
00031 
00032 namespace co
00033 {
00034 namespace base
00035 {
00036 
00038 inline void memoryBarrier()
00039 {
00040 #ifdef EQ_GCC_4_1_OR_LATER
00041     __sync_synchronize();
00042 #elif defined(_MSC_VER)
00043     _ReadWriteBarrier();
00044 #else
00045 #  error "no memory barrier implemented for this platform"
00046 #endif
00047 }
00048 
00058 template< class T > class Atomic
00059 {
00060 public:
00062     COBASE_API static T getAndAdd( T& value, const T increment );
00063 
00065     COBASE_API static T getAndSub( T& value, const T increment );
00066 
00068     static T addAndGet( T& value, const T increment );
00069 
00071     static T subAndGet( T& value, const T increment );
00072 
00074     COBASE_API static T incAndGet( T& value );
00075 
00077     COBASE_API static T decAndGet( T& value );
00078 
00080     COBASE_API static bool compareAndSwap( T* value, const T expected,
00081                                            const T newValue );
00082 
00084     explicit Atomic( const T v = 0 );
00085 
00087     Atomic( const Atomic< T >& v );
00088 
00090     operator T(void) const;
00091 
00093     void operator = ( const T v );
00094 
00096     void operator = ( const Atomic< T >& v);
00097 
00099     T operator +=(T v);
00100 
00102     T operator -=(T v);
00103 
00105     T operator ++(void);
00106 
00108     T operator --(void);
00109 
00111     T operator ++(int);
00112 
00114     T operator --(int);
00115 
00117     bool operator == ( const Atomic< T >& rhs ) const;
00118 
00120     bool operator != ( const Atomic< T >& rhs ) const;
00121 
00130     bool compareAndSwap( const T expected, const T newValue );
00131 
00132 private:
00133     mutable T _value;
00134 };
00135 
00136 typedef Atomic< int32_t > a_int32_t; 
00137 typedef Atomic< ssize_t > a_ssize_t; 
00138 
00139 // Implementation
00140 #ifdef EQ_GCC_4_1_OR_LATER
00141 template< class T > T Atomic< T >::getAndAdd( T& value, const T increment )
00142 {
00143     return __sync_fetch_and_add( &value, increment );
00144 }
00145 
00146 template< class T > T Atomic< T >::getAndSub( T& value, const T increment )
00147 {
00148     return __sync_fetch_and_sub( &value, increment );
00149 }
00150 
00151 template< class T > T Atomic< T >::addAndGet( T& value, const T increment )
00152 {
00153     return __sync_add_and_fetch( &value, increment );
00154 }
00155 
00156 template< class T > T Atomic< T >::subAndGet( T& value, const T increment )
00157 {
00158     return __sync_sub_and_fetch( &value, increment );
00159 }
00160 
00161 template< class T > T Atomic< T >::incAndGet( T& value )
00162 {
00163     return addAndGet( value, 1 );
00164 }
00165 
00166 template< class T > T Atomic< T >::decAndGet( T& value )
00167 {
00168     return subAndGet( value, 1 );
00169 }
00170 
00171 template< class T > 
00172 bool Atomic< T >::compareAndSwap( T* value, const T expected, const T newValue )
00173 {
00174     return __sync_bool_compare_and_swap( value, expected, newValue );
00175 }
00176 
00177 #elif defined (_MSC_VER)
00178 
00179 // see also atomic.cpp
00180 template< class T > T Atomic< T >::addAndGet( T& value, const T increment )
00181 {
00182     return getAndAdd( value, increment ) + increment;
00183 }
00184 
00185 template< class T > T Atomic< T >::subAndGet( T& value, const T increment )
00186 {
00187     return getAndSub( value, increment ) - increment;
00188 }
00189 
00190 #else
00191 #  error No Atomic Support - consider compareAndSwap-based implementation?
00192 #endif
00193 
00194 template< class T > Atomic< T >::Atomic ( const T v ) : _value(v) {}
00195 
00196 template <class T>
00197 Atomic< T >::Atomic( const Atomic< T >& v ) : _value( v._value ) {}
00198 
00199 template <class T>
00200 Atomic< T >::operator T(void) const
00201 {
00202     return getAndAdd( _value, 0 );
00203 }
00204 
00205 template< class T > void Atomic< T >::operator = ( const T v )
00206 {
00207     _value = v;
00208     memoryBarrier();
00209 }
00210 
00211 template< class T > void Atomic< T >::operator = ( const Atomic< T >& v)
00212 {
00213     _value = v._value;
00214     memoryBarrier();
00215 }
00216 
00217 template< class T >  T Atomic< T >::operator += (T v)
00218 {
00219     return addAndGet( _value, v );
00220 }
00221 
00222 template< class T > T Atomic< T >::operator -=(T v)
00223 {
00224     return subAndGet( _value, v );
00225 }
00226 
00227 template< class T > T Atomic< T >::operator ++(void)
00228 {
00229     return incAndGet( _value );
00230 }
00231 
00232 template< class T > T Atomic< T >::operator --(void)
00233 {
00234     return decAndGet( _value );
00235 }
00236 
00237 template< class T > T Atomic< T >::operator ++(int)
00238 {
00239     return getAndAdd( _value, 1 );
00240 }
00241 
00242 template< class T > T Atomic< T >::operator --(int)
00243 {
00244     return getAndSub( _value, 1 );
00245 }
00246 
00247 template< class T > bool Atomic< T >::operator == ( const Atomic<T>& rhs ) const
00248 {
00249     memoryBarrier();
00250     return _value == rhs._value;
00251 }
00252 
00253 template< class T > bool Atomic< T >::operator != ( const Atomic<T>& rhs ) const
00254 {
00255     memoryBarrier();
00256     return _value != rhs._value;
00257 }
00258 
00259 template< class T >
00260 bool Atomic< T >::compareAndSwap( const T expected, const T newValue )
00261 {
00262     return compareAndSwap( &_value, expected, newValue );
00263 }
00264 
00265 }
00266 }
00267 #endif  // COBASE_ATOMIC_H
Generated on Fri Jun 8 2012 15:44:29 for Equalizer 1.2.1 by  doxygen 1.8.0