#ifndef BOOST_DETAIL_ATOMIC_INTERLOCKED_HPP #define BOOST_DETAIL_ATOMIC_INTERLOCKED_HPP // Copyright (c) 2009 Helge Bahmann // // Distributed under the Boost Software License, Version 1.0. // See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include namespace boost { namespace detail { namespace atomic { static inline void full_fence(void) { long tmp; BOOST_INTERLOCKED_EXCHANGE(&tmp, 0); } template<> inline void platform_atomic_thread_fence(memory_order order) { switch(order) { case memory_order_seq_cst: full_fence(); default:; } } static inline void fence_after_load(memory_order order) { switch(order) { case memory_order_seq_cst: full_fence(); case memory_order_acquire: case memory_order_acq_rel: default:; } } template class atomic_interlocked_32 { public: explicit atomic_interlocked_32(T v) : i(v) {} atomic_interlocked_32() {} T load(memory_order order=memory_order_seq_cst) const volatile { T v=*reinterpret_cast(&i); fence_after_load(order); return v; } void store(T v, memory_order order=memory_order_seq_cst) volatile { if (order!=memory_order_seq_cst) { *reinterpret_cast(&i)=v; } else { exchange(v); } } bool compare_exchange_strong( T &expected, T desired, memory_order success_order, memory_order failure_order) volatile { T prev=expected; expected=(T)BOOST_INTERLOCKED_COMPARE_EXCHANGE((long *)(&i), (long)desired, (long)expected); bool success=(prev==expected); return success; } bool compare_exchange_weak( T &expected, T desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } T exchange(T r, memory_order order=memory_order_seq_cst) volatile { return (T)BOOST_INTERLOCKED_EXCHANGE((long *)&i, (long)r); } T fetch_add(T c, memory_order order=memory_order_seq_cst) volatile { return (T)BOOST_INTERLOCKED_EXCHANGE_ADD((long *)&i, c); } bool is_lock_free(void) const volatile {return true;} typedef T integral_type; private: T i; }; # if defined(_M_IA64) || defined(_M_AMD64) #if defined( BOOST_USE_WINDOWS_H ) # include # define BOOST_INTERLOCKED_EXCHANGE_ADD64 InterlockedExchangeAdd64 # define BOOST_INTERLOCKED_EXCHANGE64 InterlockedExchange64 # define BOOST_INTERLOCKED_COMPARE_EXCHANGE64 InterlockedCompareExchange64 #else extern "C" boost::int64_t __cdecl _InterlockedExchangeAdd64(boost::int64_t volatile *, boost::int64_t); extern "C" boost::int64_t __cdecl _InterlockedExchange64(boost::int64_t volatile *, boost::int64_t); extern "C" boost::int64_t __cdecl _InterlockedCompareExchange64(boost::int64_t volatile *, boost::int64_t, boost::int64_t); # pragma intrinsic( _InterlockedExchangeAdd64 ) # pragma intrinsic( _InterlockedExchange64 ) # pragma intrinsic( _InterlockedCompareExchange64 ) # define BOOST_INTERLOCKED_EXCHANGE_ADD64 _InterlockedExchangeAdd64 # define BOOST_INTERLOCKED_EXCHANGE64 _InterlockedExchange64 # define BOOST_INTERLOCKED_COMPARE_EXCHANGE64 _InterlockedCompareExchange64 #endif template class __declspec(align(64)) atomic_interlocked_64 { public: explicit atomic_interlocked_64(T v) : i(v) {} atomic_interlocked_64() {} T load(memory_order order=memory_order_seq_cst) const volatile { T v=*reinterpret_cast(&i); fence_after_load(order); return v; } void store(T v, memory_order order=memory_order_seq_cst) volatile { if (order!=memory_order_seq_cst) { *reinterpret_cast(&i)=v; } else { exchange(v); } } bool compare_exchange_strong( T &expected, T desired, memory_order success_order, memory_order failure_order) volatile { T prev=expected; expected=(T)BOOST_INTERLOCKED_COMPARE_EXCHANGE64((boost::int64_t *)(&i), (boost::int64_t)desired, (boost::int64_t)expected); bool success=(prev==expected); return success; } bool compare_exchange_weak( T &expected, T desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } T exchange(T r, memory_order order=memory_order_seq_cst) volatile { return (T)BOOST_INTERLOCKED_EXCHANGE64((boost::int64_t *)&i, (boost::int64_t)r); } T fetch_add(T c, memory_order order=memory_order_seq_cst) volatile { return (T)BOOST_INTERLOCKED_EXCHANGE_ADD64((boost::int64_t *)&i, c); } bool is_lock_free(void) const volatile {return true;} typedef T integral_type; private: T i; }; // _InterlockedCompareExchange128 is available only starting with VS2008 #if BOOST_MSVC >= 1500 && defined(BOOST_ATOMIC_HAVE_SSE2) #if defined( BOOST_USE_WINDOWS_H ) # include # include # define BOOST_INTERLOCKED_COMPARE_EXCHANGE128 InterlockedCompareExchange128 # pragma intrinsic( _mm_load_si128 ) # pragma intrinsic( _mm_store_si128 ) #else # include extern "C" unsigned char __cdecl _InterlockedCompareExchange128( boost::int64_t volatile *Destination, boost::int64_t ExchangeHigh, boost::int64_t ExchangeLow, boost::int64_t *Comparand) extern "C" __m128i _mm_load_si128(__m128i const*_P); extern "C" void _mm_store_si128(__m128i *_P, __m128i _B); # pragma intrinsic( _InterlockedCompareExchange128 ) # pragma intrinsic( _mm_load_si128 ) # pragma intrinsic( _mm_store_si128 ) # define BOOST_INTERLOCKED_COMPARE_EXCHANGE128 _InterlockedCompareExchange128 #endif template class __declspec(align(128)) atomic_interlocked_128 { public: explicit atomic_interlocked_128(T v) : i(v) {} atomic_interlocked_128() {} T load(memory_order order=memory_order_seq_cst) const volatile { T v; if (order!=memory_order_seq_cst) { v = _mm_load_si128(*(__m128i*)(&i)); } else { v = *reinterpret_cast(&i); } fence_after_load(order); return v; } void store(T v, memory_order order=memory_order_seq_cst) volatile { if (order!=memory_order_seq_cst) { *reinterpret_cast(&i)=v; } else { _mm_store_si128(*(__m128i*)(&i), v); } } bool compare_exchange_strong( T &expected, T desired, memory_order success_order, memory_order failure_order) volatile { boost::int64_t* desired_raw = &desired; T prev = i; bool success = BOOST_INTERLOCKED_COMPARE_EXCHANGE128( (boost::int64_t volatile *)(&i), desired_raw[1], desired_raw[0], (boost::int64_t*)&expected); if (!success) expected = prev; return success; } bool compare_exchange_weak( T &expected, T desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } T exchange(T r, memory_order order=memory_order_seq_cst) volatile { boost::int64_t* desired_raw = &r; T prev = i; while (!BOOST_INTERLOCKED_COMPARE_EXCHANGE128( (boost::int64_t volatile*)&i, desired_raw[1], desired_raw[0], (boost::int64_t*)&i)) {} return prev; } T fetch_add(T c, memory_order order=memory_order_seq_cst) volatile { T expected = i; __m128i desired; do { desired = _mm_add_epi32(*(__m128i*)(&expected), *(__m128i*)(&c)); } while (!compare_exchange_strong(expected, *(T*)(&desired), order, memory_order_relaxed)); return expected; } bool is_lock_free(void) const volatile {return true;} typedef T integral_type; private: T i; }; #endif #endif template class platform_atomic_integral : public build_atomic_from_add > { public: typedef build_atomic_from_add > super; explicit platform_atomic_integral(T v) : super(v) {} platform_atomic_integral(void) {} }; template class platform_atomic_integral: public build_atomic_from_larger_type, T> { public: typedef build_atomic_from_larger_type, T> super; explicit platform_atomic_integral(T v) : super(v) {} platform_atomic_integral(void) {} }; template class platform_atomic_integral: public build_atomic_from_larger_type, T> { public: typedef build_atomic_from_larger_type, T> super; explicit platform_atomic_integral(T v) : super(v) {} platform_atomic_integral(void) {} }; # if defined(_M_IA64) || defined(_M_AMD64) template class platform_atomic_integral : public build_atomic_from_add > { public: typedef build_atomic_from_add > super; explicit platform_atomic_integral(T v) : super(v) {} platform_atomic_integral(void) {} }; template<> class platform_atomic_integral : public build_atomic_from_add > { public: typedef build_atomic_from_add > super; explicit platform_atomic_integral(void* v) : super(v) {} platform_atomic_integral(void) {} }; #if BOOST_MSVC >= 1500 && defined(BOOST_ATOMIC_HAVE_SSE2) template class platform_atomic_integral : public build_atomic_from_add > { public: typedef build_atomic_from_add > super; explicit platform_atomic_integral(T v) : super(v) {} platform_atomic_integral(void) {} }; #endif #endif } } } #endif