Equalizer
1.2.1
|
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