From 095812d84f9fb8eb41b930aee02087f59a032a98 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Wed, 14 Feb 2018 15:26:57 +0300 Subject: [PATCH] Make the default constructor trivial if the user's type default constructor is. This requires the is_trivially_default_constructible type trait, which is not available in the older libstdc++ versions up to gcc 5.1. Thus the config macro is updated to reflect the fact that Boost.Atomic now has more advanced needs. Also, attempt to work around Intel compiler problem, which seems to break (allegedly) because of the noexcept specifiers in the defaulted default constructors. This may not be the cause, so this change will need to be tested. Also, use value_arg_type consistently across different specializations of basic_atomic. --- .../boost/atomic/detail/atomic_template.hpp | 167 ++++++++++++------ include/boost/atomic/detail/config.hpp | 4 +- .../atomic/detail/type_traits/conditional.hpp | 4 +- .../detail/type_traits/integral_constant.hpp | 4 +- .../detail/type_traits/is_floating_point.hpp | 4 +- .../atomic/detail/type_traits/is_function.hpp | 4 +- .../atomic/detail/type_traits/is_integral.hpp | 4 +- .../atomic/detail/type_traits/is_signed.hpp | 4 +- .../is_trivially_default_constructible.hpp | 46 +++++ .../atomic/detail/type_traits/make_signed.hpp | 4 +- .../detail/type_traits/make_unsigned.hpp | 4 +- 11 files changed, 179 insertions(+), 70 deletions(-) create mode 100644 include/boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp diff --git a/include/boost/atomic/detail/atomic_template.hpp b/include/boost/atomic/detail/atomic_template.hpp index a7ba338..bdff9c2 100644 --- a/include/boost/atomic/detail/atomic_template.hpp +++ b/include/boost/atomic/detail/atomic_template.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) #include #include @@ -113,12 +114,21 @@ template< typename T, typename U > struct classify< T U::*, false, false > { typedef void type; }; -template< typename T, typename Kind > -class base_atomic; +#if defined(BOOST_INTEL) +// Intel compiler (at least 18.0 update 1) breaks if noexcept specification is used in defaulted function declarations: +// error: the default constructor of "boost::atomics::atomic" cannot be referenced -- it is a deleted function +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL BOOST_NOEXCEPT +#else +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL BOOST_NOEXCEPT +#define BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL +#endif + +template< typename T, bool IsTriviallyDefaultConstructible = atomics::detail::is_trivially_default_constructible< T >::value > +class base_atomic_generic; -//! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types template< typename T > -class base_atomic< T, void > +class base_atomic_generic< T, true > { public: typedef T value_type; @@ -130,14 +140,64 @@ protected: public: typedef typename operations::storage_type storage_type; -private: - typedef atomics::detail::integral_constant< bool, sizeof(value_type) == sizeof(storage_type) > value_matches_storage; +protected: + typename operations::aligned_storage_type m_storage; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic_generic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE explicit base_atomic_generic(value_arg_type v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v)) + { + } +}; + +template< typename T > +class base_atomic_generic< T, false > +{ +public: + typedef T value_type; + +protected: + typedef atomics::detail::operations< storage_size_of< value_type >::value, false > operations; + typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type; + +public: + typedef typename operations::storage_type storage_type; protected: typename operations::aligned_storage_type m_storage; public: - BOOST_FORCEINLINE explicit base_atomic(value_arg_type v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v)) + BOOST_FORCEINLINE explicit base_atomic_generic(value_arg_type v = value_type()) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< storage_type >(v)) + { + } +}; + + +template< typename T, typename Kind > +class base_atomic; + +//! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types +template< typename T > +class base_atomic< T, void > : + public base_atomic_generic< T > +{ +private: + typedef base_atomic_generic< T > base_type; + +public: + typedef typename base_type::value_type value_type; + typedef typename base_type::storage_type storage_type; + +protected: + typedef typename base_type::operations operations; + typedef typename base_type::value_arg_type value_arg_type; + +private: + typedef atomics::detail::integral_constant< bool, sizeof(value_type) == sizeof(storage_type) > value_matches_storage; + +public: + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v) { } @@ -147,7 +207,7 @@ public: BOOST_ASSERT(order != memory_order_acquire); BOOST_ASSERT(order != memory_order_acq_rel); - operations::store(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order); + operations::store(this->m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order); } BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT @@ -155,12 +215,12 @@ public: BOOST_ASSERT(order != memory_order_release); BOOST_ASSERT(order != memory_order_acq_rel); - return atomics::detail::bitwise_cast< value_type >(operations::load(m_storage.value, order)); + return atomics::detail::bitwise_cast< value_type >(operations::load(this->m_storage.value, order)); } BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { - return atomics::detail::bitwise_cast< value_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order)); + return atomics::detail::bitwise_cast< value_type >(operations::exchange(this->m_storage.value, atomics::detail::bitwise_cast< storage_type >(v), order)); } BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT @@ -198,7 +258,7 @@ private: BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT { #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) - return operations::compare_exchange_strong(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + return operations::compare_exchange_strong(this->m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); #else return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::false_type()); #endif @@ -207,7 +267,7 @@ private: BOOST_FORCEINLINE bool compare_exchange_strong_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT { storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); - const bool res = operations::compare_exchange_strong(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + const bool res = operations::compare_exchange_strong(this->m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); expected = atomics::detail::bitwise_cast< value_type >(old_value); return res; } @@ -215,7 +275,7 @@ private: BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::true_type) volatile BOOST_NOEXCEPT { #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) - return operations::compare_exchange_weak(m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + return operations::compare_exchange_weak(this->m_storage.value, reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); #else return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::false_type()); #endif @@ -224,7 +284,7 @@ private: BOOST_FORCEINLINE bool compare_exchange_weak_impl(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order, atomics::detail::false_type) volatile BOOST_NOEXCEPT { storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); - const bool res = operations::compare_exchange_weak(m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); + const bool res = operations::compare_exchange_weak(this->m_storage.value, old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); expected = atomics::detail::bitwise_cast< value_type >(old_value); return res; } @@ -254,11 +314,11 @@ protected: typename operations::aligned_storage_type m_storage; public: - BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_NOEXCEPT, {}) - BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : m_storage(v) {} + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_CONSTEXPR explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : m_storage(v) {} // Standard methods - BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { BOOST_ASSERT(order != memory_order_consume); BOOST_ASSERT(order != memory_order_acquire); @@ -285,12 +345,12 @@ public: return atomics::detail::integral_truncate< value_type >(operations::fetch_sub(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } - BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(operations::exchange(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT { BOOST_ASSERT(failure_order != memory_order_release); BOOST_ASSERT(failure_order != memory_order_acq_rel); @@ -299,12 +359,12 @@ public: return compare_exchange_strong_impl(expected, desired, success_order, failure_order, value_matches_storage()); } - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_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)); } - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT { BOOST_ASSERT(failure_order != memory_order_release); BOOST_ASSERT(failure_order != memory_order_acq_rel); @@ -313,22 +373,22 @@ public: return compare_exchange_weak_impl(expected, desired, success_order, failure_order, value_matches_storage()); } - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_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)); } - BOOST_FORCEINLINE value_type fetch_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(operations::fetch_and(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } - BOOST_FORCEINLINE value_type fetch_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(operations::fetch_or(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } - BOOST_FORCEINLINE value_type fetch_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(operations::fetch_xor(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } @@ -359,17 +419,17 @@ public: return atomics::detail::integral_truncate< value_type >(extra_operations::negate(m_storage.value, order)); } - BOOST_FORCEINLINE value_type bitwise_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_and(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } - BOOST_FORCEINLINE value_type bitwise_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_or(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } - BOOST_FORCEINLINE value_type bitwise_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_xor(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order)); } @@ -394,17 +454,17 @@ public: extra_operations::opaque_negate(m_storage.value, order); } - BOOST_FORCEINLINE void opaque_and(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { extra_operations::opaque_and(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order); } - BOOST_FORCEINLINE void opaque_or(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { extra_operations::opaque_or(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order); } - BOOST_FORCEINLINE void opaque_xor(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { extra_operations::opaque_xor(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order); } @@ -432,19 +492,19 @@ public: } BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST - BOOST_FORCEINLINE bool and_and_test(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return extra_operations::and_and_test(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order); } BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST - BOOST_FORCEINLINE bool or_and_test(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return extra_operations::or_and_test(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order); } BOOST_ATOMIC_DETAIL_HIGHLIGHT_OP_AND_TEST - BOOST_FORCEINLINE bool xor_and_test(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return extra_operations::xor_and_test(m_storage.value, atomics::detail::integral_extend< operations::is_signed, storage_type >(v), order); } @@ -578,11 +638,11 @@ protected: operations::aligned_storage_type m_storage; public: - BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_NOEXCEPT, {}) - BOOST_CONSTEXPR explicit base_atomic(value_type v) BOOST_NOEXCEPT : m_storage(v) {} + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_CONSTEXPR explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : m_storage(v) {} // Standard methods - BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { BOOST_ASSERT(order != memory_order_consume); BOOST_ASSERT(order != memory_order_acquire); @@ -599,12 +659,12 @@ public: return !!operations::load(m_storage.value, order); } - BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { return !!operations::exchange(m_storage.value, static_cast< storage_type >(v), order); } - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT { BOOST_ASSERT(failure_order != memory_order_release); BOOST_ASSERT(failure_order != memory_order_acq_rel); @@ -613,12 +673,12 @@ public: return compare_exchange_strong_impl(expected, desired, success_order, failure_order, value_matches_storage()); } - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_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)); } - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT { BOOST_ASSERT(failure_order != memory_order_release); BOOST_ASSERT(failure_order != memory_order_acq_rel); @@ -627,7 +687,7 @@ public: return compare_exchange_weak_impl(expected, desired, success_order, failure_order, value_matches_storage()); } - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_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)); } @@ -699,8 +759,8 @@ protected: typename operations::aligned_storage_type m_storage; public: - BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_NOEXCEPT, {}) - BOOST_FORCEINLINE explicit base_atomic(value_type v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_fp_cast< storage_type >(v)) {} + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_fp_cast< storage_type >(v)) {} BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { @@ -882,13 +942,13 @@ protected: typename operations::aligned_storage_type m_storage; public: - BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_NOEXCEPT, {}) - BOOST_FORCEINLINE explicit base_atomic(value_type const& v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< uintptr_storage_type >(v)) + BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) + BOOST_FORCEINLINE explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : m_storage(atomics::detail::bitwise_cast< uintptr_storage_type >(v)) { } // Standard methods - BOOST_FORCEINLINE void store(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT { BOOST_ASSERT(order != memory_order_consume); BOOST_ASSERT(order != memory_order_acquire); @@ -920,7 +980,7 @@ public: return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::exchange(m_storage.value, atomics::detail::bitwise_cast< uintptr_storage_type >(v), order))); } - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT { BOOST_ASSERT(failure_order != memory_order_release); BOOST_ASSERT(failure_order != memory_order_acq_rel); @@ -929,12 +989,12 @@ public: return compare_exchange_strong_impl(expected, desired, success_order, failure_order, value_matches_storage()); } - BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_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)); } - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT { BOOST_ASSERT(failure_order != memory_order_release); BOOST_ASSERT(failure_order != memory_order_acq_rel); @@ -943,7 +1003,7 @@ public: return compare_exchange_weak_impl(expected, desired, success_order, failure_order, value_matches_storage()); } - BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT + BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_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)); } @@ -1069,7 +1129,7 @@ public: static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = base_type::operations::is_always_lock_free; public: - BOOST_DEFAULTED_FUNCTION(atomic() BOOST_NOEXCEPT, {}) + BOOST_DEFAULTED_FUNCTION(atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) // NOTE: The constructor is made explicit because gcc 4.7 complains that // operator=(value_arg_type) is considered ambiguous with operator=(atomic const&) @@ -1107,6 +1167,9 @@ public: template< typename T > BOOST_CONSTEXPR_OR_CONST bool atomic< T >::is_always_lock_free; +#undef BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL +#undef BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL + typedef atomic< char > atomic_char; typedef atomic< unsigned char > atomic_uchar; typedef atomic< signed char > atomic_schar; diff --git a/include/boost/atomic/detail/config.hpp b/include/boost/atomic/detail/config.hpp index f46a049..d2a6afd 100644 --- a/include/boost/atomic/detail/config.hpp +++ b/include/boost/atomic/detail/config.hpp @@ -49,8 +49,8 @@ #if defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) #if !(defined(BOOST_LIBSTDCXX11) && (BOOST_LIBSTDCXX_VERSION+0) >= 40700) /* libstdc++ from gcc >= 4.7 in C++11 mode */ -// This macro indicates that there is no standard header that is sufficient for Boost.Atomic needs. -#define BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS +// This macro indicates that there is not even a basic standard header that is sufficient for most Boost.Atomic needs. +#define BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS #endif #endif // defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) diff --git a/include/boost/atomic/detail/type_traits/conditional.hpp b/include/boost/atomic/detail/type_traits/conditional.hpp index 71397ab..6b9e896 100644 --- a/include/boost/atomic/detail/type_traits/conditional.hpp +++ b/include/boost/atomic/detail/type_traits/conditional.hpp @@ -15,7 +15,7 @@ #define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_CONDITIONAL_HPP_INCLUDED_ #include -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) #include #else #include @@ -29,7 +29,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) using std::conditional; #else using boost::conditional; diff --git a/include/boost/atomic/detail/type_traits/integral_constant.hpp b/include/boost/atomic/detail/type_traits/integral_constant.hpp index 8fbc0d5..eac8649 100644 --- a/include/boost/atomic/detail/type_traits/integral_constant.hpp +++ b/include/boost/atomic/detail/type_traits/integral_constant.hpp @@ -15,7 +15,7 @@ #define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_INTEGRAL_CONSTANT_HPP_INCLUDED_ #include -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) #include #else #include @@ -29,7 +29,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) using std::integral_constant; using std::true_type; using std::false_type; diff --git a/include/boost/atomic/detail/type_traits/is_floating_point.hpp b/include/boost/atomic/detail/type_traits/is_floating_point.hpp index cdcf269..c425112 100644 --- a/include/boost/atomic/detail/type_traits/is_floating_point.hpp +++ b/include/boost/atomic/detail/type_traits/is_floating_point.hpp @@ -15,7 +15,7 @@ #define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FLOATING_POINT_HPP_INCLUDED_ #include -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) #include #else #include @@ -29,7 +29,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) using std::is_floating_point; #else using boost::is_floating_point; diff --git a/include/boost/atomic/detail/type_traits/is_function.hpp b/include/boost/atomic/detail/type_traits/is_function.hpp index 7b82840..e720535 100644 --- a/include/boost/atomic/detail/type_traits/is_function.hpp +++ b/include/boost/atomic/detail/type_traits/is_function.hpp @@ -15,7 +15,7 @@ #define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_FUNCTION_HPP_INCLUDED_ #include -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) #include #else #include @@ -29,7 +29,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) using std::is_function; #else using boost::is_function; diff --git a/include/boost/atomic/detail/type_traits/is_integral.hpp b/include/boost/atomic/detail/type_traits/is_integral.hpp index 5deb120..ef3e2e3 100644 --- a/include/boost/atomic/detail/type_traits/is_integral.hpp +++ b/include/boost/atomic/detail/type_traits/is_integral.hpp @@ -16,7 +16,7 @@ #include // Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) #include #else #include @@ -30,7 +30,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) using std::is_integral; #else using boost::is_integral; diff --git a/include/boost/atomic/detail/type_traits/is_signed.hpp b/include/boost/atomic/detail/type_traits/is_signed.hpp index bf95163..2dc1df7 100644 --- a/include/boost/atomic/detail/type_traits/is_signed.hpp +++ b/include/boost/atomic/detail/type_traits/is_signed.hpp @@ -16,7 +16,7 @@ #include // Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) #include #else #include @@ -30,7 +30,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) using std::is_signed; #else using boost::is_signed; diff --git a/include/boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp b/include/boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp new file mode 100644 index 0000000..5f88b88 --- /dev/null +++ b/include/boost/atomic/detail/type_traits/is_trivially_default_constructible.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) 2018 Andrey Semashev + */ +/*! + * \file atomic/detail/type_traits/is_trivially_default_constructible.hpp + * + * This header defines \c is_trivially_default_constructible type trait + */ + +#ifndef BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ +#define BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ + +#include +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +#include +#else +#include +#endif + +#ifdef BOOST_HAS_PRAGMA_ONCE +#pragma once +#endif + +namespace boost { +namespace atomics { +namespace detail { + +#if !defined(BOOST_NO_CXX11_HDR_TYPE_TRAITS) +using std::is_trivially_default_constructible; +#elif !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES) +template< typename T > +using is_trivially_default_constructible = boost::has_trivial_constructor< T >; +#else +template< typename T > +struct is_trivially_default_constructible : public boost::has_trivial_constructor< T > {}; +#endif + +} // namespace detail +} // namespace atomics +} // namespace boost + +#endif // BOOST_ATOMIC_DETAIL_TYPE_TRAITS_IS_TRIVIALLY_DEFAULT_CONSTRUCTIBLE_HPP_INCLUDED_ diff --git a/include/boost/atomic/detail/type_traits/make_signed.hpp b/include/boost/atomic/detail/type_traits/make_signed.hpp index 831efdc..82f61b3 100644 --- a/include/boost/atomic/detail/type_traits/make_signed.hpp +++ b/include/boost/atomic/detail/type_traits/make_signed.hpp @@ -16,7 +16,7 @@ #include // Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) #include #else #include @@ -30,7 +30,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) using std::make_signed; #else using boost::make_signed; diff --git a/include/boost/atomic/detail/type_traits/make_unsigned.hpp b/include/boost/atomic/detail/type_traits/make_unsigned.hpp index c4eb020..573a161 100644 --- a/include/boost/atomic/detail/type_traits/make_unsigned.hpp +++ b/include/boost/atomic/detail/type_traits/make_unsigned.hpp @@ -16,7 +16,7 @@ #include // Some versions of libstdc++ don't consider __int128 an integral type. Use Boost.TypeTraits because of that. -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) #include #else #include @@ -30,7 +30,7 @@ namespace boost { namespace atomics { namespace detail { -#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) +#if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_BASIC_HDR_TYPE_TRAITS) && !defined(BOOST_HAS_INT128) using std::make_unsigned; #else using boost::make_unsigned;