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) 2018 Andrey Semashev 7 */ 8 /*! 9 * \file atomic/detail/extra_ops_emulated.hpp 10 * 11 * This header contains emulated (lock-based) implementation of the extra atomic operations. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_EXTRA_OPS_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/extra_operations_fwd.hpp> 23 #include <boost/atomic/detail/header.hpp> 24 25 #ifdef BOOST_HAS_PRAGMA_ONCE 26 #pragma once 27 #endif 28 29 namespace boost { 30 namespace atomics { 31 namespace detail { 32 33 //! Emulated implementation of extra operations 34 template< typename Base, std::size_t Size, bool Signed > 35 struct extra_operations_emulated : 36 public Base 37 { 38 typedef Base base_type; 39 typedef typename base_type::storage_type storage_type; 40 typedef typename base_type::scoped_lock scoped_lock; 41 fetch_negateboost::atomics::detail::extra_operations_emulated42 static storage_type fetch_negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 43 { 44 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 45 storage_type& s = const_cast< storage_type& >(storage); 46 scoped_lock lock(&storage); 47 storage_type old_val = s; 48 s = static_cast< storage_type >(-old_val); 49 return old_val; 50 } 51 negateboost::atomics::detail::extra_operations_emulated52 static storage_type negate(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 53 { 54 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 55 storage_type& s = const_cast< storage_type& >(storage); 56 scoped_lock lock(&storage); 57 storage_type new_val = static_cast< storage_type >(-s); 58 s = new_val; 59 return new_val; 60 } 61 addboost::atomics::detail::extra_operations_emulated62 static storage_type add(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 63 { 64 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 65 storage_type& s = const_cast< storage_type& >(storage); 66 scoped_lock lock(&storage); 67 storage_type new_val = s; 68 new_val += v; 69 s = new_val; 70 return new_val; 71 } 72 subboost::atomics::detail::extra_operations_emulated73 static storage_type sub(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 74 { 75 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 76 storage_type& s = const_cast< storage_type& >(storage); 77 scoped_lock lock(&storage); 78 storage_type new_val = s; 79 new_val -= v; 80 s = new_val; 81 return new_val; 82 } 83 bitwise_andboost::atomics::detail::extra_operations_emulated84 static storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 85 { 86 BOOST_STATIC_ASSERT_MSG(!base_type::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 new_val = s; 90 new_val &= v; 91 s = new_val; 92 return new_val; 93 } 94 bitwise_orboost::atomics::detail::extra_operations_emulated95 static storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 96 { 97 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 98 storage_type& s = const_cast< storage_type& >(storage); 99 scoped_lock lock(&storage); 100 storage_type new_val = s; 101 new_val |= v; 102 s = new_val; 103 return new_val; 104 } 105 bitwise_xorboost::atomics::detail::extra_operations_emulated106 static storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order) BOOST_NOEXCEPT 107 { 108 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 109 storage_type& s = const_cast< storage_type& >(storage); 110 scoped_lock lock(&storage); 111 storage_type new_val = s; 112 new_val ^= v; 113 s = new_val; 114 return new_val; 115 } 116 fetch_complementboost::atomics::detail::extra_operations_emulated117 static storage_type fetch_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 118 { 119 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 120 storage_type& s = const_cast< storage_type& >(storage); 121 scoped_lock lock(&storage); 122 storage_type old_val = s; 123 s = static_cast< storage_type >(~old_val); 124 return old_val; 125 } 126 bitwise_complementboost::atomics::detail::extra_operations_emulated127 static storage_type bitwise_complement(storage_type volatile& storage, memory_order) BOOST_NOEXCEPT 128 { 129 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 130 storage_type& s = const_cast< storage_type& >(storage); 131 scoped_lock lock(&storage); 132 storage_type new_val = static_cast< storage_type >(~s); 133 s = new_val; 134 return new_val; 135 } 136 opaque_addboost::atomics::detail::extra_operations_emulated137 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 138 { 139 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 140 base_type::fetch_add(storage, v, order); 141 } 142 opaque_subboost::atomics::detail::extra_operations_emulated143 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 144 { 145 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 146 base_type::fetch_sub(storage, v, order); 147 } 148 opaque_negateboost::atomics::detail::extra_operations_emulated149 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 150 { 151 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 152 fetch_negate(storage, order); 153 } 154 opaque_andboost::atomics::detail::extra_operations_emulated155 static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 156 { 157 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 158 base_type::fetch_and(storage, v, order); 159 } 160 opaque_orboost::atomics::detail::extra_operations_emulated161 static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 162 { 163 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 164 base_type::fetch_or(storage, v, order); 165 } 166 opaque_xorboost::atomics::detail::extra_operations_emulated167 static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 168 { 169 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 170 base_type::fetch_xor(storage, v, order); 171 } 172 opaque_complementboost::atomics::detail::extra_operations_emulated173 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 174 { 175 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 176 fetch_complement(storage, order); 177 } 178 add_and_testboost::atomics::detail::extra_operations_emulated179 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 180 { 181 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 182 return !!add(storage, v, order); 183 } 184 sub_and_testboost::atomics::detail::extra_operations_emulated185 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 186 { 187 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 188 return !!sub(storage, v, order); 189 } 190 negate_and_testboost::atomics::detail::extra_operations_emulated191 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 192 { 193 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 194 return !!negate(storage, order); 195 } 196 and_and_testboost::atomics::detail::extra_operations_emulated197 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 198 { 199 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 200 return !!bitwise_and(storage, v, order); 201 } 202 or_and_testboost::atomics::detail::extra_operations_emulated203 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 204 { 205 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 206 return !!bitwise_or(storage, v, order); 207 } 208 xor_and_testboost::atomics::detail::extra_operations_emulated209 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT 210 { 211 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 212 return !!bitwise_xor(storage, v, order); 213 } 214 complement_and_testboost::atomics::detail::extra_operations_emulated215 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT 216 { 217 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 218 return !!bitwise_complement(storage, order); 219 } 220 bit_test_and_setboost::atomics::detail::extra_operations_emulated221 static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 222 { 223 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 224 storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); 225 storage_type old_val = base_type::fetch_or(storage, mask, order); 226 return !!(old_val & mask); 227 } 228 bit_test_and_resetboost::atomics::detail::extra_operations_emulated229 static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 230 { 231 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 232 storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); 233 storage_type old_val = base_type::fetch_and(storage, ~mask, order); 234 return !!(old_val & mask); 235 } 236 bit_test_and_complementboost::atomics::detail::extra_operations_emulated237 static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT 238 { 239 BOOST_STATIC_ASSERT_MSG(!base_type::is_interprocess, "Boost.Atomic: operation invoked on a non-lock-free inter-process atomic object"); 240 storage_type mask = static_cast< storage_type >(static_cast< storage_type >(1u) << bit_number); 241 storage_type old_val = base_type::fetch_xor(storage, mask, order); 242 return !!(old_val & mask); 243 } 244 }; 245 246 template< typename Base, std::size_t Size, bool Signed > 247 struct extra_operations< Base, Size, Signed, false > : 248 public extra_operations_emulated< Base, Size, Signed > 249 { 250 }; 251 252 } // namespace detail 253 } // namespace atomics 254 } // namespace boost 255 256 #include <boost/atomic/detail/footer.hpp> 257 258 #endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_EMULATED_HPP_INCLUDED_ 259