#ifndef BOOST_ATOMIC_DETAIL_CAS32STRONG_HPP #define BOOST_ATOMIC_DETAIL_CAS32STRONG_HPP // 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) // // Copyright (c) 2011 Helge Bahmann // Build 8-, 16- and 32-bit atomic operations from // a platform_cmpxchg32_strong primitive. #include #include #include #include #include #ifdef BOOST_ATOMIC_HAS_PRAGMA_ONCE #pragma once #endif namespace boost { namespace atomics { namespace detail { /* integral types */ template class base_atomic { typedef base_atomic this_type; typedef T value_type; typedef T difference_type; typedef uint32_t storage_type; public: explicit base_atomic(value_type v) : v_(v) {} base_atomic(void) {} void store(value_type v, memory_order order = memory_order_seq_cst) volatile { platform_fence_before_store(order); const_cast(v_) = v; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { value_type v = const_cast(v_); platform_fence_after_load(order); return v; } value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { platform_fence_before(success_order); storage_type expected_s = (storage_type) expected; storage_type desired_s = (storage_type) desired; bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); expected = (value_type) expected_s; } return success; } value_type fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed)); return original; } value_type fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed)); return original; } value_type fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed)); return original; } value_type fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed)); return original; } value_type fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed)); return original; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; storage_type v_; }; template class base_atomic { typedef base_atomic this_type; typedef T value_type; typedef T difference_type; typedef uint32_t storage_type; public: explicit base_atomic(value_type v) : v_(v) {} base_atomic(void) {} void store(value_type v, memory_order order = memory_order_seq_cst) volatile { platform_fence_before_store(order); const_cast(v_) = v; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { value_type v = const_cast(v_); platform_fence_after_load(order); return v; } value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { platform_fence_before(success_order); storage_type expected_s = (storage_type) expected; storage_type desired_s = (storage_type) desired; bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); expected = (value_type) expected_s; } return success; } value_type fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed)); return original; } value_type fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed)); return original; } value_type fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed)); return original; } value_type fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed)); return original; } value_type fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed)); return original; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; storage_type v_; }; template class base_atomic { typedef base_atomic this_type; typedef T value_type; typedef T difference_type; public: explicit base_atomic(value_type v) : v_(v) {} base_atomic(void) {} void store(value_type v, memory_order order = memory_order_seq_cst) volatile { platform_fence_before_store(order); const_cast(v_) = v; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { value_type v = const_cast(v_); platform_fence_after_load(order); return v; } value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { platform_fence_before(success_order); bool success = platform_cmpxchg32_strong(expected, desired, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); } return success; } value_type fetch_add(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed)); return original; } value_type fetch_sub(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed)); return original; } value_type fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original & v, order, memory_order_relaxed)); return original; } value_type fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original | v, order, memory_order_relaxed)); return original; } value_type fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original ^ v, order, memory_order_relaxed)); return original; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_INTEGRAL_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; value_type v_; }; /* pointer types */ template class base_atomic { typedef base_atomic this_type; typedef void * value_type; typedef ptrdiff_t difference_type; public: explicit base_atomic(value_type v) : v_(v) {} base_atomic(void) {} void store(value_type v, memory_order order = memory_order_seq_cst) volatile { platform_fence_before_store(order); const_cast(v_) = v; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { value_type v = const_cast(v_); platform_fence_after_load(order); return v; } value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { platform_fence_before(success_order); bool success = platform_cmpxchg32_strong(expected, desired, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); } return success; } value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed)); return original; } value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed)); return original; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_BASE_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; value_type v_; }; template class base_atomic { typedef base_atomic this_type; typedef T * value_type; typedef ptrdiff_t difference_type; public: explicit base_atomic(value_type v) : v_(v) {} base_atomic(void) {} void store(value_type v, memory_order order = memory_order_seq_cst) volatile { platform_fence_before_store(order); const_cast(v_) = v; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { value_type v = const_cast(v_); platform_fence_after_load(order); return v; } value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type desired, memory_order success_order, memory_order failure_order) volatile { platform_fence_before(success_order); bool success = platform_cmpxchg32_strong(expected, desired, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); } return success; } value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original + v, order, memory_order_relaxed)); return original; } value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, original - v, order, memory_order_relaxed)); return original; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_POINTER_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; value_type v_; }; /* generic types */ template class base_atomic { typedef base_atomic this_type; typedef T value_type; typedef uint32_t storage_type; public: explicit base_atomic(value_type const& v) { memcpy(&v_, &v, sizeof(value_type)); } base_atomic(void) {} void store(value_type const& v, memory_order order = memory_order_seq_cst) volatile { storage_type tmp = 0; memcpy(&tmp, &v, sizeof(value_type)); platform_fence_before_store(order); const_cast(v_) = tmp; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { storage_type tmp = const_cast(v_); platform_fence_after_load(order); value_type v; memcpy(&v, &tmp, sizeof(value_type)); return v; } value_type exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type const& desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type const& desired, memory_order success_order, memory_order failure_order) volatile { storage_type expected_s = 0, desired_s = 0; memcpy(&expected_s, &expected, sizeof(value_type)); memcpy(&desired_s, &desired, sizeof(value_type)); platform_fence_before(success_order); bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); memcpy(&expected, &expected_s, sizeof(value_type)); } return success; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_BASE_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; storage_type v_; }; template class base_atomic { typedef base_atomic this_type; typedef T value_type; typedef uint32_t storage_type; public: explicit base_atomic(value_type const& v) { memcpy(&v_, &v, sizeof(value_type)); } base_atomic(void) {} void store(value_type const& v, memory_order order = memory_order_seq_cst) volatile { storage_type tmp = 0; memcpy(&tmp, &v, sizeof(value_type)); platform_fence_before_store(order); const_cast(v_) = tmp; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { storage_type tmp = const_cast(v_); platform_fence_after_load(order); value_type v; memcpy(&v, &tmp, sizeof(value_type)); return v; } value_type exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type const& desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type const& desired, memory_order success_order, memory_order failure_order) volatile { storage_type expected_s = 0, desired_s = 0; memcpy(&expected_s, &expected, sizeof(value_type)); memcpy(&desired_s, &desired, sizeof(value_type)); platform_fence_before(success_order); bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); memcpy(&expected, &expected_s, sizeof(value_type)); } return success; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_BASE_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; storage_type v_; }; template class base_atomic { typedef base_atomic this_type; typedef T value_type; typedef uint32_t storage_type; public: explicit base_atomic(value_type const& v) : v_(0) { memcpy(&v_, &v, sizeof(value_type)); } base_atomic(void) {} void store(value_type const& v, memory_order order = memory_order_seq_cst) volatile { storage_type tmp = 0; memcpy(&tmp, &v, sizeof(value_type)); platform_fence_before_store(order); const_cast(v_) = tmp; platform_fence_after_store(order); } value_type load(memory_order order = memory_order_seq_cst) const volatile { storage_type tmp = const_cast(v_); platform_fence_after_load(order); value_type v; memcpy(&v, &tmp, sizeof(value_type)); return v; } value_type exchange(value_type const& v, memory_order order = memory_order_seq_cst) volatile { value_type original = load(memory_order_relaxed); do { } while (!compare_exchange_weak(original, v, order, memory_order_relaxed)); return original; } bool compare_exchange_weak( value_type & expected, value_type const& desired, memory_order success_order, memory_order failure_order) volatile { return compare_exchange_strong(expected, desired, success_order, failure_order); } bool compare_exchange_strong( value_type & expected, value_type const& desired, memory_order success_order, memory_order failure_order) volatile { storage_type expected_s = 0, desired_s = 0; memcpy(&expected_s, &expected, sizeof(value_type)); memcpy(&desired_s, &desired, sizeof(value_type)); platform_fence_before(success_order); bool success = platform_cmpxchg32_strong(expected_s, desired_s, &v_); if (success) { platform_fence_after(success_order); } else { platform_fence_after(failure_order); memcpy(&expected, &expected_s, sizeof(value_type)); } return success; } bool is_lock_free(void) const volatile { return true; } BOOST_ATOMIC_DECLARE_BASE_OPERATORS private: base_atomic(const base_atomic &) /* = delete */ ; void operator=(const base_atomic &) /* = delete */ ; storage_type v_; }; } } } #endif