pion-net
4.0.9
|
00001 // Copyright (C) 2007, 2008 Tim Blechmann & Thomas Grill 00002 // 00003 // Distributed under the Boost Software License, Version 1.0. (See 00004 // accompanying file LICENSE_1_0.txt or copy at 00005 // http://www.boost.org/LICENSE_1_0.txt) 00006 00007 // Disclaimer: Not a Boost library. 00008 00009 #ifndef BOOST_LOCKFREE_ATOMIC_INT_HPP 00010 #define BOOST_LOCKFREE_ATOMIC_INT_HPP 00011 00012 #include <boost/lockfree/detail/prefix.hpp> 00013 #include <boost/lockfree/detail/cas.hpp> 00014 #include <boost/noncopyable.hpp> 00015 00016 namespace boost 00017 { 00018 namespace lockfree 00019 { 00020 00021 #if defined(__GNUC__) && ( (__GNUC__ > 4) || ((__GNUC__ >= 4) && (__GNUC_MINOR__ >= 1)) ) || __INTEL_COMPILER 00022 00023 template <typename T> 00024 class atomic_int: 00025 boost::noncopyable 00026 { 00027 public: 00028 explicit atomic_int(T v = 0): 00029 value(v) 00030 {} 00031 00032 operator T(void) const 00033 { 00034 return __sync_fetch_and_add(&value, 0); 00035 } 00036 00037 void operator =(T v) 00038 { 00039 value = v; 00040 __sync_synchronize(); 00041 } 00042 00043 T operator +=(T v) 00044 { 00045 return __sync_add_and_fetch(&value, v); 00046 } 00047 00048 T operator -=(T v) 00049 { 00050 return __sync_sub_and_fetch(&value, v); 00051 } 00052 00053 /* prefix operator */ 00054 T operator ++(void) 00055 { 00056 return __sync_add_and_fetch(&value, 1); 00057 } 00058 00059 /* prefix operator */ 00060 T operator --(void) 00061 { 00062 return __sync_sub_and_fetch(&value, 1); 00063 } 00064 00065 /* postfix operator */ 00066 T operator ++(int) 00067 { 00068 return __sync_fetch_and_add(&value, 1); 00069 } 00070 00071 /* postfix operator */ 00072 T operator --(int) 00073 { 00074 return __sync_fetch_and_sub(&value, 1); 00075 } 00076 00077 private: 00078 mutable T value; 00079 }; 00080 00081 #elif defined(__GLIBCPP__) || defined(__GLIBCXX__) 00082 00083 template <typename T> 00084 class atomic_int: 00085 boost::noncopyable 00086 { 00087 public: 00088 explicit atomic_int(T v = 0): 00089 value(v) 00090 {} 00091 00092 operator T(void) const 00093 { 00094 return __gnu_cxx::__exchange_and_add(&value, 0); 00095 } 00096 00097 void operator =(T v) 00098 { 00099 value = v; 00100 } 00101 00102 T operator +=(T v) 00103 { 00104 return __gnu_cxx::__exchange_and_add(&value, v) + v; 00105 } 00106 00107 T operator -=(T v) 00108 { 00109 return __gnu_cxx::__exchange_and_add(&value, -v) - v; 00110 } 00111 00112 /* prefix operator */ 00113 T operator ++(void) 00114 { 00115 return operator+=(1); 00116 } 00117 00118 /* prefix operator */ 00119 T operator --(void) 00120 { 00121 return operator-=(1); 00122 } 00123 00124 /* postfix operator */ 00125 T operator ++(int) 00126 { 00127 return __gnu_cxx::__exchange_and_add(&value, 1); 00128 } 00129 00130 /* postfix operator */ 00131 T operator --(int) 00132 { 00133 return __gnu_cxx::__exchange_and_add(&value, -1); 00134 } 00135 00136 private: 00137 mutable _Atomic_word value; 00138 }; 00139 00140 #else /* emulate via atomic_cas */ 00141 00142 template <typename T> 00143 class atomic_int: 00144 boost::noncopyable 00145 { 00146 public: 00147 explicit atomic_int(T v = 0) 00148 { 00149 *this = v; 00150 } 00151 00152 operator T(void) const 00153 { 00154 memory_barrier(); 00155 return value; 00156 } 00157 00158 void operator =(T v) 00159 { 00160 value = v; 00161 memory_barrier(); 00162 } 00163 00164 /* prefix operator */ 00165 T operator ++() 00166 { 00167 return *this += 1; 00168 } 00169 00170 /* prefix operator */ 00171 T operator --() 00172 { 00173 return *this -= 1; 00174 } 00175 00176 T operator +=(T v) 00177 { 00178 for(;;) 00179 { 00180 T oldv = value; 00181 T newv = oldv + v; 00182 if(likely(atomic_cas(&value, oldv, newv))) 00183 return newv; 00184 } 00185 } 00186 00187 T operator -=(T v) 00188 { 00189 for(;;) 00190 { 00191 T oldv = value; 00192 T newv = oldv - v; 00193 00194 if(likely(atomic_cas(&value, oldv, newv))) 00195 return newv; 00196 } 00197 } 00198 00199 /* postfix operator */ 00200 T operator ++(int) 00201 { 00202 for(;;) 00203 { 00204 T oldv = value; 00205 if(likely(atomic_cas(&value, oldv, oldv+1))) 00206 return oldv; 00207 } 00208 } 00209 00210 /* postfix operator */ 00211 T operator --(int) 00212 { 00213 for(;;) 00214 { 00215 T oldv = value; 00216 if(likely(atomic_cas(&value, oldv, oldv-1))) 00217 return oldv; 00218 } 00219 } 00220 00221 private: 00222 T value; 00223 }; 00224 00225 00226 #endif 00227 00228 } /* namespace lockfree */ 00229 } /* namespace boost */ 00230 00231 #endif /* BOOST_LOCKFREE_ATOMIC_INT_HPP */