00001 #ifndef BOOST_DETAIL_ATOMIC_GENERIC_CAS_HPP
00002 #define BOOST_DETAIL_ATOMIC_GENERIC_CAS_HPP
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdint.h>
00011
00012 #include <boost/memory_order.hpp>
00013 #include <boost/atomic/detail/base.hpp>
00014 #include <boost/atomic/detail/builder.hpp>
00015
00016
00017
00018
00019
00020
00021 #if defined(__GNUC__)
00022 namespace boost { namespace detail { namespace atomic {
00023 static inline int32_t
00024 fenced_compare_exchange_strong_32(volatile int32_t *ptr, int32_t expected, int32_t desired)
00025 {
00026 return __sync_val_compare_and_swap_4(ptr, expected, desired);
00027 }
00028 #define BOOST_ATOMIC_HAVE_CAS32 1
00029
00030 #if defined(__amd64__) || defined(__i686__)
00031 static inline int64_t
00032 fenced_compare_exchange_strong_64(int64_t *ptr, int64_t expected, int64_t desired)
00033 {
00034 return __sync_val_compare_and_swap_8(ptr, expected, desired);
00035 }
00036 #define BOOST_ATOMIC_HAVE_CAS64 1
00037 #endif
00038 }}}
00039
00040 #elif defined(__ICL) || defined(_MSC_VER)
00041
00042 #if defined(_MSC_VER)
00043 #include <Windows.h>
00044 #include <intrin.h>
00045 #endif
00046
00047 namespace boost { namespace detail { namespace atomic {
00048 static inline int32_t
00049 fenced_compare_exchange_strong(int32_t *ptr, int32_t expected, int32_t desired)
00050 {
00051 return _InterlockedCompareExchange(reinterpret_cast<volatile long*>(ptr), desired, expected);
00052 }
00053 #define BOOST_ATOMIC_HAVE_CAS32 1
00054 #if defined(_WIN64)
00055 static inline int64_t
00056 fenced_compare_exchange_strong(int64_t *ptr, int64_t expected, int64_t desired)
00057 {
00058 return _InterlockedCompareExchange64(ptr, desired, expected);
00059 }
00060 #define BOOST_ATOMIC_HAVE_CAS64 1
00061 #endif
00062 }}}
00063
00064 #elif (defined(__ICC) || defined(__ECC))
00065 namespace boost { namespace detail { namespace atomic {
00066 static inline int32_t
00067 fenced_compare_exchange_strong_32(int32_t *ptr, int32_t expected, int32_t desired)
00068 {
00069 return _InterlockedCompareExchange((void*)ptr, desired, expected);
00070 }
00071 #define BOOST_ATOMIC_HAVE_CAS32 1
00072 #if defined(__x86_64)
00073 static inline int64_t
00074 fenced_compare_exchange_strong(int64_t *ptr, int64_t expected, int64_t desired)
00075 {
00076 return cas64<int>(ptr, expected, desired);
00077 }
00078 #define BOOST_ATOMIC_HAVE_CAS64 1
00079 #elif defined(__ECC) //IA-64 version
00080 static inline int64_t
00081 fenced_compare_exchange_strong(int64_t *ptr, int64_t expected, int64_t desired)
00082 {
00083 return _InterlockedCompareExchange64((void*)ptr, desired, expected);
00084 }
00085 #define BOOST_ATOMIC_HAVE_CAS64 1
00086 #endif
00087 }}}
00088
00089 #elif (defined(__SUNPRO_CC) && defined(__sparc))
00090 #include <sys/atomic.h>
00091 namespace boost { namespace detail { namespace atomic {
00092 static inline int32_t
00093 fenced_compare_exchange_strong_32(int32_t *ptr, int32_t expected, int32_t desired)
00094 {
00095 return atomic_cas_32((volatile unsigned int*)ptr, expected, desired);
00096 }
00097 #define BOOST_ATOMIC_HAVE_CAS32 1
00098
00099
00100 static inline int64_t
00101 fenced_compare_exchange_strong_64(int64_t *ptr, int64_t expected, int64_t desired)
00102 {
00103 return atomic_cas_64((volatile unsigned long long*)ptr, expected, desired);
00104 }
00105 #define BOOST_ATOMIC_HAVE_CAS64 1
00106 }}}
00107 #endif
00108
00109
00110 namespace boost { namespace detail { namespace atomic {
00111
00112 #ifdef BOOST_ATOMIC_HAVE_CAS32
00113 template<typename T>
00114 class atomic_generic_cas32 {
00115 private:
00116 typedef atomic_generic_cas32 this_type;
00117 public:
00118 explicit atomic_generic_cas32(T v) : i((int32_t)v) {}
00119 atomic_generic_cas32() {}
00120 T load(memory_order order=memory_order_seq_cst) const volatile
00121 {
00122 T expected=(T)i;
00123 do { } while(!const_cast<this_type *>(this)->compare_exchange_weak(expected, expected, order, memory_order_relaxed));
00124 return expected;
00125 }
00126 void store(T v, memory_order order=memory_order_seq_cst) volatile
00127 {
00128 exchange(v);
00129 }
00130 bool compare_exchange_strong(
00131 T &expected,
00132 T desired,
00133 memory_order success_order,
00134 memory_order failure_order) volatile
00135 {
00136 T found;
00137 found=(T)fenced_compare_exchange_strong_32(&i, (int32_t)expected, (int32_t)desired);
00138 bool success=(found==expected);
00139 expected=found;
00140 return success;
00141 }
00142 bool compare_exchange_weak(
00143 T &expected,
00144 T desired,
00145 memory_order success_order,
00146 memory_order failure_order) volatile
00147 {
00148 return compare_exchange_strong(expected, desired, success_order, failure_order);
00149 }
00150 T exchange(T r, memory_order order=memory_order_seq_cst) volatile
00151 {
00152 T expected=(T)i;
00153 do { } while(!compare_exchange_weak(expected, r, order, memory_order_relaxed));
00154 return expected;
00155 }
00156
00157 bool is_lock_free(void) const volatile {return true;}
00158 typedef T integral_type;
00159 private:
00160 mutable int32_t i;
00161 };
00162
00163 template<typename T>
00164 class platform_atomic_integral<T, 4> : public build_atomic_from_exchange<atomic_generic_cas32<T> > {
00165 public:
00166 typedef build_atomic_from_exchange<atomic_generic_cas32<T> > super;
00167 explicit platform_atomic_integral(T v) : super(v) {}
00168 platform_atomic_integral(void) {}
00169 };
00170
00171 template<typename T>
00172 class platform_atomic_integral<T, 1>: public build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> {
00173 public:
00174 typedef build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> super;
00175
00176 explicit platform_atomic_integral(T v) : super(v) {}
00177 platform_atomic_integral(void) {}
00178 };
00179
00180 template<typename T>
00181 class platform_atomic_integral<T, 2>: public build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> {
00182 public:
00183 typedef build_atomic_from_larger_type<atomic_generic_cas32<int32_t>, T> super;
00184
00185 explicit platform_atomic_integral(T v) : super(v) {}
00186 platform_atomic_integral(void) {}
00187 };
00188 #endif
00189
00190 } } }
00191
00192 #endif