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