common/include/boost/lockfree/atomic_int.hpp

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 */

Generated on Fri Apr 30 14:48:53 2010 for pion-net by  doxygen 1.4.7