From f3d59ec1c17c26e4e2e9ad67d01ee17cd893bff0 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Sat, 19 Apr 2014 22:25:02 +0400 Subject: [PATCH] Working on the new library design. Added implementation of atomic ops with gcc __atomic intrinsics. Implemented the unified atomic interface. Extracted atomic_flag to a separate header. atomic_flag now follows standard requirements for static initialization, if possible. --- include/boost/atomic/capabilities.hpp | 5 + include/boost/atomic/detail/atomic_flag.hpp | 79 +++ .../boost/atomic/detail/atomic_template.hpp | 561 ++++++++++++++++++ include/boost/atomic/detail/caps_gcc_sync.hpp | 19 +- include/boost/atomic/detail/int_sizes.hpp | 9 + .../atomic/detail/operations_lockfree.hpp | 28 + .../boost/atomic/detail/ops_gcc_atomic.hpp | 175 ++++++ include/boost/atomic/detail/storage_types.hpp | 84 +++ .../atomic/detail/type-classification.hpp | 45 -- include/boost/atomic/detail/union_cast.hpp | 46 ++ 10 files changed, 1004 insertions(+), 47 deletions(-) create mode 100644 include/boost/atomic/detail/atomic_flag.hpp create mode 100644 include/boost/atomic/detail/atomic_template.hpp create mode 100644 include/boost/atomic/detail/operations_lockfree.hpp create mode 100644 include/boost/atomic/detail/ops_gcc_atomic.hpp create mode 100644 include/boost/atomic/detail/storage_types.hpp delete mode 100644 include/boost/atomic/detail/type-classification.hpp create mode 100644 include/boost/atomic/detail/union_cast.hpp diff --git a/include/boost/atomic/capabilities.hpp b/include/boost/atomic/capabilities.hpp index f8fb542..34bef48 100644 --- a/include/boost/atomic/capabilities.hpp +++ b/include/boost/atomic/capabilities.hpp @@ -127,6 +127,11 @@ #endif #ifndef BOOST_ATOMIC_POINTER_LOCK_FREE +#if (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 8 +#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT64_LOCK_FREE +#elif (BOOST_ATOMIC_DETAIL_SIZEOF_POINTER + 0) == 4 +#define BOOST_ATOMIC_POINTER_LOCK_FREE BOOST_ATOMIC_INT32_LOCK_FREE +#else #define BOOST_ATOMIC_POINTER_LOCK_FREE 0 #endif diff --git a/include/boost/atomic/detail/atomic_flag.hpp b/include/boost/atomic/detail/atomic_flag.hpp new file mode 100644 index 0000000..fcab30e --- /dev/null +++ b/include/boost/atomic/detail/atomic_flag.hpp @@ -0,0 +1,79 @@ +/* + * 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) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/atomic_flag.hpp + * + * This header contains interface definition of \c atomic_flag. + */ + +#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { + +#if defined(BOOST_NO_CXX11_CONSTEXPR) +#define BOOST_ATOMIC_NO_STATIC_INIT_ATOMIC_FLAG +#endif + +#if !defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) && !defined(BOOST_ATOMIC_DEFAULT_INITIALIZE_ATOMIC_FLAG) +#define BOOST_ATOMIC_FLAG_INIT { 0 } +#else +namespace detail { +struct default_initializer {}; +BOOST_CONSTEXPR_OR_CONST default_initializer default_init = {}; +} // namespace detail +#define BOOST_ATOMIC_FLAG_INIT ::boost::atomics::detail::default_init +#endif + +struct atomic_flag +{ + typedef atomics::detail::operations< 1u > operations; + typedef operations::storage_type storage_type; + + storage_type m_storage; + +#if !defined(BOOST_ATOMIC_DEFAULT_INITIALIZE_ATOMIC_FLAG) +#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) + BOOST_CONSTEXPR atomic_flag() BOOST_NOEXCEPT = default; +#else + BOOST_CONSTEXPR atomic_flag() BOOST_NOEXCEPT {} +#endif +#if defined(BOOST_NO_CXX11_UNIFIED_INITIALIZATION_SYNTAX) + BOOST_CONSTEXPR atomic_flag(atomics::detail::default_initializer) BOOST_NOEXCEPT : m_storage(0) {} +#endif +#else + BOOST_CONSTEXPR atomic_flag() BOOST_NOEXCEPT : m_storage(0) {} + BOOST_CONSTEXPR atomic_flag(atomics::detail::default_initializer) BOOST_NOEXCEPT : m_storage(0) {} +#endif + + bool test_and_set(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return operations::test_and_set(m_storage, order); + } + + void clear(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + operations::clear(m_storage, order); + } + + BOOST_DELETED_FUNCTION(atomic_flag(atomic_flag const&)) + BOOST_DELETED_FUNCTION(atomic_flag& operator= (atomic_flag const&)) +}; + +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_ATOMIC_FLAG_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/atomic_template.hpp b/include/boost/atomic/detail/atomic_template.hpp new file mode 100644 index 0000000..b901b18 --- /dev/null +++ b/include/boost/atomic/detail/atomic_template.hpp @@ -0,0 +1,561 @@ +/* + * 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) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/atomic_template.hpp + * + * This header contains interface definition of \c atomic template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_ATOMIC_TEMPLATE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_ATOMIC_TEMPLATE_HPP_INCLUDED_ + +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +BOOST_FORCEINLINE BOOST_CONSTEXPR memory_order deduce_failure_order(memory_order order) BOOST_NOEXCEPT +{ + return order == memory_order_acq_rel ? memory_order_acquire : (order == memory_order_release ? memory_order_relaxed : order); +} + +template< typename T, bool IsInt = boost::is_integral< T >::value > +struct classify +{ + typedef void type; +}; + +template< typename T > +struct classify< T, true > { typedef int type; }; + +template< typename T > +struct classify< T*, false > { typedef void* type; }; + +template< typename T, typename Kind > +class base_atomic; + +//! Implementation for integers +template< typename T > +class base_atomic< T, int > +{ +private: + typedef base_atomic this_type; + typedef T value_type; + typedef T difference_type; + typedef operations< storage_size_of< value_type >::value > operations; + +protected: + typedef value_type value_arg_type; + +public: + typedef typename operations::storage_type storage_type; + +protected: + storage_type m_storage; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic(), {}) + BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : m_storage(v) {} + + void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + operations::store(m_storage, static_cast< storage_type >(v), order); + } + + value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::load(m_storage, order)); + } + + value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::fetch_add(m_storage, static_cast< storage_type >(v), order)); + } + + value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::fetch_sub(m_storage, static_cast< storage_type >(v), order)); + } + + value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::exchange(m_storage, static_cast< storage_type >(v), order)); + } + + bool compare_exchange_strong( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = operations::compare_exchange_strong(m_storage, old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = static_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool compare_exchange_weak( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = static_cast< storage_type >(expected); + const bool res = operations::compare_exchange_weak(m_storage, old_value, static_cast< storage_type >(desired), success_order, failure_order); + expected = static_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + value_type fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::fetch_and(m_storage, static_cast< storage_type >(v), order)); + } + + value_type fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::fetch_or(m_storage, static_cast< storage_type >(v), order)); + } + + value_type fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return static_cast< value_type >(operations::fetch_xor(m_storage, static_cast< storage_type >(v), order)); + } + + bool is_lock_free() const volatile BOOST_NOEXCEPT + { + return operations::is_lock_free(m_storage); + } + + value_type operator++(int) volatile BOOST_NOEXCEPT + { + return fetch_add(1); + } + + value_type operator++() volatile BOOST_NOEXCEPT + { + return fetch_add(1) + 1; + } + + value_type operator--(int) volatile BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + value_type operator--() volatile BOOST_NOEXCEPT + { + return fetch_sub(1) - 1; + } + + value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT + { + return fetch_add(v) + v; + } + + value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT + { + return fetch_sub(v) - v; + } + + value_type operator&=(value_type v) volatile BOOST_NOEXCEPT + { + return fetch_and(v) & v; + } + + value_type operator|=(value_type v) volatile BOOST_NOEXCEPT + { + return fetch_or(v) | v; + } + + value_type operator^=(value_type v) volatile BOOST_NOEXCEPT + { + return fetch_xor(v) ^ v; + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) +}; + + +//! Implementation for user-defined types, such as structs and enums +template< typename T > +class base_atomic< T, void > +{ +private: + typedef base_atomic this_type; + typedef T value_type; + typedef operations< storage_size_of< value_type >::value > operations; + +protected: + typedef value_type const& value_arg_type; + +public: + typedef typename operations::storage_type storage_type; + +protected: + storage_type m_storage; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic(), {}) + explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::union_cast< storage_type >(v)) + { + } + + void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + operations::store(m_storage, atomics::detail::union_cast< storage_type >(v), order); + } + + value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::load(m_storage, order)); + } + + value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::exchange(m_storage, atomics::detail::union_cast< storage_type >(v), order)); + } + + bool compare_exchange_strong( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::union_cast< storage_type >(expected); + const bool res = operations::compare_exchange_strong(m_storage, old_value, atomics::detail::union_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::union_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool compare_exchange_weak( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::union_cast< storage_type >(expected); + const bool res = operations::compare_exchange_weak(m_storage, old_value, atomics::detail::union_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::union_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool is_lock_free() const volatile BOOST_NOEXCEPT + { + return operations::is_lock_free(m_storage); + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) +}; + + +//! Implementation for pointers +template +class base_atomic< T*, void* > +{ +private: + typedef base_atomic this_type; + typedef T* value_type; + typedef std::ptrdiff_t difference_type; + typedef operations< storage_size_of< value_type >::value > operations; + +protected: + typedef value_type value_arg_type; + +public: + typedef typename operations::storage_type storage_type; + +protected: + storage_type m_storage; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic(void), {}) + explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::union_cast< storage_type >(v)) + { + } + + void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + operations::store(m_storage, atomics::detail::union_cast< storage_type >(v), order); + } + + value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::load(m_storage, order)); + } + + value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::fetch_add(m_storage, static_cast< storage_type >(v * sizeof(T)), order)); + } + + value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::fetch_sub(m_storage, static_cast< storage_type >(v * sizeof(T)), order)); + } + + value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::exchange(m_storage, atomics::detail::union_cast< storage_type >(v), order)); + } + + bool compare_exchange_strong( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::union_cast< storage_type >(expected); + const bool res = operations::compare_exchange_strong(m_storage, old_value, atomics::detail::union_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::union_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool compare_exchange_weak( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::union_cast< storage_type >(expected); + const bool res = operations::compare_exchange_weak(m_storage, old_value, atomics::detail::union_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::union_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool is_lock_free() const volatile BOOST_NOEXCEPT + { + return operations::is_lock_free(m_storage); + } + + value_type operator++(int) volatile BOOST_NOEXCEPT + { + return fetch_add(1); + } + + value_type operator++() volatile BOOST_NOEXCEPT + { + return fetch_add(1) + 1; + } + + value_type operator--(int) volatile BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + value_type operator--() volatile BOOST_NOEXCEPT + { + return fetch_sub(1) - 1; + } + + value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT + { + return fetch_add(v) + v; + } + + value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT + { + return fetch_sub(v) - v; + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) +}; + + +//! Implementation for void pointers +template< > +class base_atomic< void*, void* > +{ +private: + typedef base_atomic this_type; + typedef void* value_type; + typedef std::ptrdiff_t difference_type; + typedef operations< storage_size_of< value_type >::value > operations; + +protected: + typedef value_type value_arg_type; + +public: + typedef typename operations::storage_type storage_type; + +protected: + storage_type m_storage; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic(void), {}) + explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::union_cast< storage_type >(v)) + { + } + + void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + operations::store(m_storage, atomics::detail::union_cast< storage_type >(v), order); + } + + value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::load(m_storage, order)); + } + + value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::fetch_add(m_storage, static_cast< storage_type >(v * sizeof(T)), order)); + } + + value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::fetch_sub(m_storage, static_cast< storage_type >(v * sizeof(T)), order)); + } + + value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return atomics::detail::union_cast< value_type >(operations::exchange(m_storage, atomics::detail::union_cast< storage_type >(v), order)); + } + + bool compare_exchange_strong( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::union_cast< storage_type >(expected); + const bool res = operations::compare_exchange_strong(m_storage, old_value, atomics::detail::union_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::union_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool compare_exchange_weak( + value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + { + storage_type old_value = atomics::detail::union_cast< storage_type >(expected); + const bool res = operations::compare_exchange_weak(m_storage, old_value, atomics::detail::union_cast< storage_type >(desired), success_order, failure_order); + expected = atomics::detail::union_cast< value_type >(old_value); + return res; + } + + bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + { + return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); + } + + bool is_lock_free() const volatile BOOST_NOEXCEPT + { + return operations::is_lock_free(m_storage); + } + + value_type operator++(int) volatile BOOST_NOEXCEPT + { + return fetch_add(1); + } + + value_type operator++() volatile BOOST_NOEXCEPT + { + return (char*)fetch_add(1) + 1; + } + + value_type operator--(int) volatile BOOST_NOEXCEPT + { + return fetch_sub(1); + } + + value_type operator--() volatile BOOST_NOEXCEPT + { + return (char*)fetch_sub(1) - 1; + } + + value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT + { + return (char*)fetch_add(v) + v; + } + + value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT + { + return (char*)fetch_sub(v) - v; + } + + BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) + BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) +}; + +} // namespace detail + +template< typename T > +class atomic : + public atomics::detail::base_atomic< + T, + typename atomics::detail::classify< T >::type + > +{ +private: + typedef T value_type; + typedef atomics::detail::base_atomic< + T, + typename atomics::detail::classify< T >::type + > base_type; + typedef typename base_type::value_arg_type value_arg_type; + +public: + typedef typename base_type::storage_type storage_type; + +public: + BOOST_DEFAULTED_FUNCTION(atomic(), BOOST_NOEXCEPT {}) + + // NOTE: The constructor is made explicit because gcc 4.7 complains that + // operator=(value_arg_type) is considered ambiguous with operator=(atomic const&) + // in assignment expressions, even though conversion to atomic<> is less preferred + // than conversion to value_arg_type. + explicit BOOST_CONSTEXPR atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v) {} + + BOOST_FORCEINLINE value_type operator= (value_arg_type v) volatile BOOST_NOEXCEPT + { + this->store(v); + return v; + } + + BOOST_FORCEINLINE operator value_type() volatile const BOOST_NOEXCEPT + { + return this->load(); + } + + BOOST_FORCEINLINE storage_type& storage() BOOST_NOEXCEPT { return this->m_storage; } + BOOST_FORCEINLINE storage_type volatile& storage() volatile BOOST_NOEXCEPT { return this->m_storage; } + BOOST_FORCEINLINE storage_type const& storage() const BOOST_NOEXCEPT { return this->m_storage; } + BOOST_FORCEINLINE storage_type const volatile& storage() const volatile BOOST_NOEXCEPT { return this->m_storage; } + + BOOST_DELETED_FUNCTION(atomic(atomic const&)) + BOOST_DELETED_FUNCTION(atomic& operator= (atomic const&) volatile) +}; + +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_ATOMIC_TEMPLATE_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/caps_gcc_sync.hpp b/include/boost/atomic/detail/caps_gcc_sync.hpp index 37f5923..43065fe 100644 --- a/include/boost/atomic/detail/caps_gcc_sync.hpp +++ b/include/boost/atomic/detail/caps_gcc_sync.hpp @@ -22,16 +22,31 @@ #pragma once #endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) #define BOOST_ATOMIC_INT8_LOCK_FREE 2 +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) #define BOOST_ATOMIC_INT16_LOCK_FREE 2 +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) #define BOOST_ATOMIC_INT32_LOCK_FREE 2 -#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8) +#endif +#if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)\ + || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) #define BOOST_ATOMIC_INT64_LOCK_FREE 2 #endif #if defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16) #define BOOST_ATOMIC_INT128_LOCK_FREE 2 #endif -#define BOOST_ATOMIC_POINTER_LOCK_FREE 2 #define BOOST_ATOMIC_THREAD_FENCE 2 #define BOOST_ATOMIC_SIGNAL_FENCE 2 diff --git a/include/boost/atomic/detail/int_sizes.hpp b/include/boost/atomic/detail/int_sizes.hpp index 5545ca1..3d6f0cf 100644 --- a/include/boost/atomic/detail/int_sizes.hpp +++ b/include/boost/atomic/detail/int_sizes.hpp @@ -36,6 +36,15 @@ #if defined(__SIZEOF_WCHAR_T__) #define BOOST_ATOMIC_DETAIL_SIZEOF_WCHAR_T __SIZEOF_WCHAR_T__ #endif +#if defined(__SIZEOF_POINTER__) +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER __SIZEOF_POINTER__ +#elif defined(_MSC_VER) +#if defined(_M_AMD64) || defined(_M_IA64) +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 8 +#else +#define BOOST_ATOMIC_DETAIL_SIZEOF_POINTER 4 +#endif +#endif #if !defined(BOOST_ATOMIC_DETAIL_SIZEOF_SHORT) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_INT) ||\ !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LONG) || !defined(BOOST_ATOMIC_DETAIL_SIZEOF_LLONG) diff --git a/include/boost/atomic/detail/operations_lockfree.hpp b/include/boost/atomic/detail/operations_lockfree.hpp new file mode 100644 index 0000000..544c04b --- /dev/null +++ b/include/boost/atomic/detail/operations_lockfree.hpp @@ -0,0 +1,28 @@ +/* + * 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) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/operations_lockfree.hpp + * + * This header defines lockfree atomic operations. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_ + +#include +#include + +#if !defined(BOOST_ATOMIC_EMULATED) +#include BOOST_ATOMIC_DETAIL_HEADER(boost/atomic/detail/ops_) +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +#endif // BOOST_ATOMIC_DETAIL_OPERATIONS_LOCKFREE_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/ops_gcc_atomic.hpp b/include/boost/atomic/detail/ops_gcc_atomic.hpp new file mode 100644 index 0000000..1895b81 --- /dev/null +++ b/include/boost/atomic/detail/ops_gcc_atomic.hpp @@ -0,0 +1,175 @@ +/* + * 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) 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/ops_gcc_atomic.hpp + * + * This header contains implementation of the \c operations template. + */ + +#ifndef BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ + +#include +#include +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +BOOST_FORCEINLINE BOOST_CONSTEXPR int convert_memory_order_to_gcc(memory_order order) BOOST_NOEXCEPT +{ + return (order == memory_order_relaxed ? __ATOMIC_RELAXED : (order == memory_order_consume ? __ATOMIC_CONSUME : + (order == memory_order_acquire ? __ATOMIC_ACQUIRE : (order == memory_order_release ? __ATOMIC_RELEASE : + (order == memory_order_acq_rel ? __ATOMIC_ACQ_REL : __ATOMIC_SEQ_CST))))); +} + +template< typename T > +struct gcc_atomic_operations +{ + typedef T storage_type; + + static BOOST_FORCEINLINE void store(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + __atomic_store_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type load(storage_type const volatile& storage, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_load_n(&storage, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_fetch_add(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_fetch_sub(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type exchange(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_exchange_n(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE bool compare_exchange_strong( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return __atomic_compare_exchange_n + ( + &storage, &expected, desired, false, + atomics::detail::convert_memory_order_to_gcc(success_order), + atomics::detail::convert_memory_order_to_gcc(failure_order) + ); + } + + static BOOST_FORCEINLINE bool compare_exchange_weak( + storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT + { + return __atomic_compare_exchange_n + ( + &storage, &expected, desired, true, + atomics::detail::convert_memory_order_to_gcc(success_order), + atomics::detail::convert_memory_order_to_gcc(failure_order) + ); + } + + static BOOST_FORCEINLINE storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_fetch_and(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_fetch_or(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_fetch_xor(&storage, v, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + return __atomic_test_and_set(&storage, atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT + { + __atomic_clear(const_cast< storage_type* >(&storage), atomics::detail::convert_memory_order_to_gcc(order)); + } + + static BOOST_FORCEINLINE bool is_lock_free(storage_type const volatile& storage) BOOST_NOEXCEPT + { + return __atomic_is_lock_free(sizeof(storage_type), &storage); + } +}; + +#if BOOST_ATOMIC_INT8_LOCK_FREE > 0 +template< > +struct operations< 1u > : + public gcc_atomic_operations< storage8_t > +{ +}; +#endif + +#if BOOST_ATOMIC_INT16_LOCK_FREE > 0 +template< > +struct operations< 2u > : + public gcc_atomic_operations< storage16_t > +{ +}; +#endif + +#if BOOST_ATOMIC_INT32_LOCK_FREE > 0 +template< > +struct operations< 4u > : + public gcc_atomic_operations< storage32_t > +{ +}; +#endif + +#if BOOST_ATOMIC_INT64_LOCK_FREE > 0 +template< > +struct operations< 8u > : + public gcc_atomic_operations< storage64_t > +{ +}; +#endif + +#if BOOST_ATOMIC_INT128_LOCK_FREE > 0 +template< > +struct operations< 16u > : + public gcc_atomic_operations< storage128_t > +{ +}; +#endif + +} // namespace detail + +BOOST_FORCEINLINE void atomic_thread_fence(memory_order order) +{ + __atomic_thread_fence(atomics::detail::convert_memory_order_to_gcc(order)); +} + +BOOST_FORCEINLINE void atomic_signal_fence(memory_order order) +{ + __atomic_signal_fence(atomics::detail::convert_memory_order_to_gcc(order)); +} + +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_OPS_GCC_ATOMIC_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/storage_types.hpp b/include/boost/atomic/detail/storage_types.hpp new file mode 100644 index 0000000..9738500 --- /dev/null +++ b/include/boost/atomic/detail/storage_types.hpp @@ -0,0 +1,84 @@ +/* + * 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) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2013 - 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/storage_types.hpp + * + * This header defines underlying types used as storage + */ + +#ifndef BOOST_ATOMIC_DETAIL_STORAGE_TYPES_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_STORAGE_TYPES_HPP_INCLUDED_ + +#include +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +typedef boost::uint8_t storage8_t; +typedef boost::uint16_t storage16_t; +typedef boost::uint32_t storage32_t; + +#if !defined(BOOST_NO_INT64_T) +typedef boost::uint64_t storage64_t; +#else +struct BOOST_ALIGNMENT(8) storage64_t +{ + boost::uint32_t data[2]; +}; + +BOOST_FORCEINLINE bool operator== (storage64_t const& left, storage64_t const& right) BOOST_NOEXCEPT +{ + return left.data[0] == right.data[0] && left.data[1] == right.data[1]; +} +BOOST_FORCEINLINE bool operator!= (storage64_t const& left, storage64_t const& right) BOOST_NOEXCEPT +{ + return !(left == right); +} +#endif + +#if !defined(BOOST_HAS_INT128) +typedef boost::uint128_type storage128_t; +#else +struct BOOST_ALIGNMENT(16) storage128_t +{ + storage64_t data[2]; +}; + +BOOST_FORCEINLINE bool operator== (storage128_t const& left, storage128_t const& right) BOOST_NOEXCEPT +{ + return left.data[0] == right.data[0] && left.data[1] == right.data[1]; +} +BOOST_FORCEINLINE bool operator!= (storage128_t const& left, storage128_t const& right) BOOST_NOEXCEPT +{ + return !(left == right); +} +#endif + +template< typename T > +struct storage_size_of +{ + enum _ + { + size = sizeof(T), + value = (size == 3 ? 4 : (size >= 5 && size <= 7 ? 8 : (size >= 9 && size <= 15 ? 16 : size))) + }; +}; + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_STORAGE_TYPES_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/type-classification.hpp b/include/boost/atomic/detail/type-classification.hpp deleted file mode 100644 index 98bc311..0000000 --- a/include/boost/atomic/detail/type-classification.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef BOOST_ATOMIC_DETAIL_TYPE_CLASSIFICATION_HPP -#define BOOST_ATOMIC_DETAIL_TYPE_CLASSIFICATION_HPP - -// Copyright (c) 2011 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 - -#ifdef BOOST_HAS_PRAGMA_ONCE -#pragma once -#endif - -namespace boost { -namespace atomics { -namespace detail { - -template::value> -struct classify -{ - typedef void type; -}; - -template -struct classify {typedef int type;}; - -template -struct classify {typedef void* type;}; - -template -struct storage_size_of -{ - enum _ - { - size = sizeof(T), - value = (size == 3 ? 4 : (size >= 5 && size <= 7 ? 8 : (size >= 9 && size <= 15 ? 16 : size))) - }; -}; - -}}} - -#endif diff --git a/include/boost/atomic/detail/union_cast.hpp b/include/boost/atomic/detail/union_cast.hpp new file mode 100644 index 0000000..19fa3a4 --- /dev/null +++ b/include/boost/atomic/detail/union_cast.hpp @@ -0,0 +1,46 @@ +/* + * 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) 2009 Helge Bahmann + * Copyright (c) 2012 Tim Blechmann + * Copyright (c) 2013 - 2014 Andrey Semashev + */ +/*! + * \file atomic/detail/union_cast.hpp + * + * This header defines \c union_cast used to convert between storage and value types + */ + +#ifndef BOOST_ATOMIC_DETAIL_UNION_CAST_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_UNION_CAST_HPP_INCLUDED_ + +#include + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +template< typename To, typename From > +BOOST_FORCEINLINE To union_cast(From const& from) BOOST_NOEXCEPT +{ + union + { + To as_to; + From as_from; + } + caster = {}; + caster.as_from = from; + return caster.as_to; +} + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_UNION_CAST_HPP_INCLUDED_