1 /* 2 * Distributed under the Boost Software License, Version 1.0. 3 * (See accompanying file LICENSE_1_0.txt or copy at 4 * http://www.boost.org/LICENSE_1_0.txt) 5 * 6 * Copyright (c) 2014, 2020 Andrey Semashev 7 */ 8 /*! 9 * \file atomic/detail/core_operations_emulated.hpp 10 * 11 * This header contains lock pool-based implementation of the core atomic operations. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_ 16 17 #include <cstddef> 18 #include <boost/static_assert.hpp> 19 #include <boost/memory_order.hpp> 20 #include <boost/atomic/detail/config.hpp> 21 #include <boost/atomic/detail/storage_traits.hpp> 22 #include <boost/atomic/detail/core_operations_emulated_fwd.hpp> 23 #include <boost/atomic/detail/lock_pool.hpp> 24 #include <boost/atomic/detail/header.hpp> 25 26 #ifdef BOOST_HAS_PRAGMA_ONCE 27 #pragma once 28 #endif 29 30 namespace boost { 31 namespace atomics { 32 namespace detail { 33 34 template< std::size_t Size, std::size_t Alignment, bool = Alignment >= storage_traits< Size >::native_alignment > 35 struct core_operations_emulated_base 36 { 37 typedef typename storage_traits< Size >::type storage_type; 38 }; 39 40 template< std::size_t Size, std::size_t Alignment > 41 struct core_operations_emulated_base< Size, Alignment, false > 42 { 43 typedef buffer_storage< Size, Alignment > storage_type; 44 }; 45 46 //! Emulated implementation of core atomic operations 47 template< std::size_t Size, std::size_t Alignment, bool Signed, bool Interprocess > 48 struct core_operations_emulated : 49 public core_operations_emulated_base< Size, Alignment > 50 { 51 typedef core_operations_emulated_base< Size, Alignment > base_type; 52 53 // Define storage_type to have alignment not greater than Alignment. This will allow operations to work with value_types 54 // that possibly have weaker alignment requirements than storage_traits< Size >::type would. This is important for atomic_ref<>. 55 // atomic<> will allow higher alignment requirement than its value_type. 56 // Note that storage_type should be an integral type, if possible, so that arithmetic and bitwise operations are possible. 57 typedef typename base_type::storage_type storage_type; 58 59 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_size = Size; 60 static BOOST_CONSTEXPR_OR_CONST std::size_t storage_alignment = Alignment >= storage_traits< Size >::alignment ? storage_traits< Size >::alignment : Alignment; 61 62 static BOOST_CONSTEXPR_OR_CONST bool is_signed = Signed; 63 static BOOST_CONSTEXPR_OR_CONST bool is_interprocess = Interprocess; 64 static BOOST_CONSTEXPR_OR_CONST bool full_cas_based = false; 65 66 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = false; 67 68 typedef lock_pool::scoped_lock< storage_alignment > scoped_lock; 69 storeboost::atomics::detail::core_operations_emulated70 static void store(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 71 { 72 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 73 scoped_lock lock(&storage); 74 const_cast< storage_type& >(storage) = v; 75 } 76 loadboost::atomics::detail::core_operations_emulated77 static storage_type load(storage_type const volatile& storage, memory_order) BOOST_NOEXCEPT 78 { 79 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 80 scoped_lock lock(&storage); 81 return const_cast< storage_type const& >(storage); 82 } 83 fetch_addboost::atomics::detail::core_operations_emulated84 static storage_type fetch_add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 85 { 86 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 87 storage_type& s = const_cast< storage_type& >(storage); 88 scoped_lock lock(&storage); 89 storage_type old_val = s; 90 s += v; 91 return old_val; 92 } 93 fetch_subboost::atomics::detail::core_operations_emulated94 static storage_type fetch_sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 95 { 96 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 97 storage_type& s = const_cast< storage_type& >(storage); 98 scoped_lock lock(&storage); 99 storage_type old_val = s; 100 s -= v; 101 return old_val; 102 } 103 exchangeboost::atomics::detail::core_operations_emulated104 static storage_type exchange(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 105 { 106 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 107 storage_type& s = const_cast< storage_type& >(storage); 108 scoped_lock lock(&storage); 109 storage_type old_val = s; 110 s = v; 111 return old_val; 112 } 113 compare_exchange_strongboost::atomics::detail::core_operations_emulated114 static bool compare_exchange_strong( 115 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT 116 { 117 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 118 storage_type& s = const_cast< storage_type& >(storage); 119 scoped_lock lock(&storage); 120 storage_type old_val = s; 121 const bool res = old_val == expected; 122 if (res) 123 s = desired; 124 expected = old_val; 125 126 return res; 127 } 128 compare_exchange_weakboost::atomics::detail::core_operations_emulated129 static bool compare_exchange_weak( 130 storage_type volatile& storage, storage_type& expected, storage_type desired, memory_order, memory_order) BOOST_NOEXCEPT 131 { 132 // Note: This function is the exact copy of compare_exchange_strong. The reason we're not just forwarding the call 133 // is that MSVC-12 ICEs in this case. 134 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 135 storage_type& s = const_cast< storage_type& >(storage); 136 scoped_lock lock(&storage); 137 storage_type old_val = s; 138 const bool res = old_val == expected; 139 if (res) 140 s = desired; 141 expected = old_val; 142 143 return res; 144 } 145 fetch_andboost::atomics::detail::core_operations_emulated146 static storage_type fetch_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 147 { 148 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 149 storage_type& s = const_cast< storage_type& >(storage); 150 scoped_lock lock(&storage); 151 storage_type old_val = s; 152 s &= v; 153 return old_val; 154 } 155 fetch_orboost::atomics::detail::core_operations_emulated156 static storage_type fetch_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 157 { 158 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 159 storage_type& s = const_cast< storage_type& >(storage); 160 scoped_lock lock(&storage); 161 storage_type old_val = s; 162 s |= v; 163 return old_val; 164 } 165 fetch_xorboost::atomics::detail::core_operations_emulated166 static storage_type fetch_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 167 { 168 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 169 storage_type& s = const_cast< storage_type& >(storage); 170 scoped_lock lock(&storage); 171 storage_type old_val = s; 172 s ^= v; 173 return old_val; 174 } 175 test_and_setboost::atomics::detail::core_operations_emulated176 static BOOST_FORCEINLINE bool test_and_set(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 177 { 178 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 179 return !!exchange(storage, (storage_type)1, order); 180 } 181 clearboost::atomics::detail::core_operations_emulated182 static BOOST_FORCEINLINE void clear(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 183 { 184 BOOST_STATIC_ASSERT_MSG(!is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 185 store(storage, (storage_type)0, order); 186 } 187 }; 188 189 } // namespace detail 190 } // namespace atomics 191 } // namespace boost 192 193 #include <boost/atomic/detail/footer.hpp> 194 195 #endif // BOOST_ATOMIC_DETAIL_CORE_OPERATIONS_EMULATED_HPP_INCLUDED_ 196