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) 2020 Andrey Semashev 7 */ 8 /*! 9 * \file atomic/detail/atomic_ref_impl.hpp 10 * 11 * This header contains implementation of \c atomic_ref template. 12 */ 13 14 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_REF_IMPL_HPP_INCLUDED_ 15 #define BOOST_ATOMIC_DETAIL_ATOMIC_REF_IMPL_HPP_INCLUDED_ 16 17 #include <cstddef> 18 #include <boost/assert.hpp> 19 #include <boost/memory_order.hpp> 20 #include <boost/atomic/detail/config.hpp> 21 #include <boost/atomic/detail/addressof.hpp> 22 #include <boost/atomic/detail/storage_traits.hpp> 23 #include <boost/atomic/detail/bitwise_cast.hpp> 24 #include <boost/atomic/detail/core_operations.hpp> 25 #include <boost/atomic/detail/wait_operations.hpp> 26 #include <boost/atomic/detail/extra_operations.hpp> 27 #include <boost/atomic/detail/core_operations_emulated.hpp> 28 #include <boost/atomic/detail/memory_order_utils.hpp> 29 #include <boost/atomic/detail/type_traits/is_signed.hpp> 30 #include <boost/atomic/detail/type_traits/alignment_of.hpp> 31 #include <boost/atomic/detail/type_traits/conditional.hpp> 32 #include <boost/atomic/detail/type_traits/integral_constant.hpp> 33 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) 34 #include <boost/atomic/detail/bitwise_fp_cast.hpp> 35 #include <boost/atomic/detail/fp_operations.hpp> 36 #include <boost/atomic/detail/extra_fp_operations.hpp> 37 #endif 38 #include <boost/atomic/detail/header.hpp> 39 40 #ifdef BOOST_HAS_PRAGMA_ONCE 41 #pragma once 42 #endif 43 44 /* 45 * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE, 46 * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp. 47 */ 48 49 namespace boost { 50 namespace atomics { 51 namespace detail { 52 53 template< typename T, bool Signed, bool Interprocess > 54 struct is_atomic_ref_lock_free 55 { 56 typedef T value_type; 57 typedef atomics::detail::core_operations< sizeof(value_type), Signed, Interprocess > core_operations; 58 typedef typename core_operations::storage_type storage_type; 59 60 static BOOST_CONSTEXPR_OR_CONST bool value = sizeof(value_type) == sizeof(storage_type) && core_operations::is_always_lock_free; 61 }; 62 63 template< typename T, bool Signed, bool Interprocess > 64 class base_atomic_ref_common 65 { 66 public: 67 typedef T value_type; 68 69 protected: 70 typedef typename atomics::detail::conditional< 71 atomics::detail::is_atomic_ref_lock_free< T, Signed, Interprocess >::value, 72 atomics::detail::core_operations< sizeof(value_type), Signed, Interprocess >, 73 atomics::detail::core_operations_emulated< sizeof(value_type), atomics::detail::alignment_of< value_type >::value, Signed, Interprocess > 74 >::type core_operations; 75 typedef atomics::detail::wait_operations< core_operations > wait_operations; 76 typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type; 77 typedef typename core_operations::storage_type storage_type; 78 BOOST_STATIC_ASSERT_MSG(sizeof(storage_type) == sizeof(value_type), "Boost.Atomic internal error: atomic_ref storage size doesn't match the value size"); 79 80 public: 81 static BOOST_CONSTEXPR_OR_CONST std::size_t required_alignment = atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment ? core_operations::storage_alignment : atomics::detail::alignment_of< value_type >::value; 82 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free; 83 static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify; 84 85 protected: 86 value_type* m_value; 87 88 public: base_atomic_ref_common(value_type & v)89 BOOST_FORCEINLINE explicit base_atomic_ref_common(value_type& v) BOOST_NOEXCEPT : m_value(atomics::detail::addressof(v)) 90 { 91 } 92 value() const93 BOOST_FORCEINLINE value_type& value() const BOOST_NOEXCEPT { return *m_value; } 94 95 protected: storage() const96 BOOST_FORCEINLINE storage_type& storage() const BOOST_NOEXCEPT 97 { 98 return *reinterpret_cast< storage_type* >(m_value); 99 } 100 101 public: is_lock_free() const102 BOOST_FORCEINLINE bool is_lock_free() const BOOST_NOEXCEPT 103 { 104 // C++20 specifies that is_lock_free returns true if operations on *all* objects of the atomic_ref<T> type are lock-free. 105 // This does not allow to return true or false depending on the referenced object runtime alignment. Currently, Boost.Atomic 106 // follows this specification, although we may support runtime alignment checking in the future. 107 return is_always_lock_free; 108 } 109 has_native_wait_notify() const110 BOOST_FORCEINLINE bool has_native_wait_notify() const BOOST_NOEXCEPT 111 { 112 return wait_operations::has_native_wait_notify(this->storage()); 113 } 114 notify_one() const115 BOOST_FORCEINLINE void notify_one() const BOOST_NOEXCEPT 116 { 117 wait_operations::notify_one(this->storage()); 118 } 119 notify_all() const120 BOOST_FORCEINLINE void notify_all() const BOOST_NOEXCEPT 121 { 122 wait_operations::notify_all(this->storage()); 123 } 124 }; 125 126 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES) 127 template< typename T, bool Signed, bool Interprocess > 128 BOOST_CONSTEXPR_OR_CONST std::size_t base_atomic_ref_common< T, Signed, Interprocess >::required_alignment; 129 template< typename T, bool Signed, bool Interprocess > 130 BOOST_CONSTEXPR_OR_CONST bool base_atomic_ref_common< T, Signed, Interprocess >::is_always_lock_free; 131 template< typename T, bool Signed, bool Interprocess > 132 BOOST_CONSTEXPR_OR_CONST bool base_atomic_ref_common< T, Signed, Interprocess >::always_has_native_wait_notify; 133 #endif 134 135 136 template< typename T, typename Kind, bool Interprocess > 137 class base_atomic_ref; 138 139 //! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types 140 template< typename T, bool Interprocess > 141 class base_atomic_ref< T, void, Interprocess > : 142 public base_atomic_ref_common< T, false, Interprocess > 143 { 144 private: 145 typedef base_atomic_ref_common< T, false, Interprocess > base_type; 146 147 public: 148 typedef typename base_type::value_type value_type; 149 150 protected: 151 typedef typename base_type::core_operations core_operations; 152 typedef typename base_type::wait_operations wait_operations; 153 typedef typename base_type::storage_type storage_type; 154 typedef typename base_type::value_arg_type value_arg_type; 155 156 private: 157 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast; 158 159 public: base_atomic_ref(base_atomic_ref const & that)160 BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) 161 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) 162 { 163 } 164 store(value_arg_type v,memory_order order=memory_order_seq_cst) const165 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 166 { 167 BOOST_ASSERT(order != memory_order_consume); 168 BOOST_ASSERT(order != memory_order_acquire); 169 BOOST_ASSERT(order != memory_order_acq_rel); 170 171 core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order); 172 } 173 load(memory_order order=memory_order_seq_cst) const174 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 175 { 176 BOOST_ASSERT(order != memory_order_release); 177 BOOST_ASSERT(order != memory_order_acq_rel); 178 179 return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); 180 } 181 exchange(value_arg_type v,memory_order order=memory_order_seq_cst) const182 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 183 { 184 return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order)); 185 } 186 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const187 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 188 { 189 BOOST_ASSERT(failure_order != memory_order_release); 190 BOOST_ASSERT(failure_order != memory_order_acq_rel); 191 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 192 193 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 194 } 195 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const196 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 197 { 198 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); 199 } 200 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const201 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 202 { 203 BOOST_ASSERT(failure_order != memory_order_release); 204 BOOST_ASSERT(failure_order != memory_order_acq_rel); 205 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 206 207 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 208 } 209 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const210 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 211 { 212 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); 213 } 214 wait(value_arg_type old_val,memory_order order=memory_order_seq_cst) const215 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 216 { 217 BOOST_ASSERT(order != memory_order_release); 218 BOOST_ASSERT(order != memory_order_acq_rel); 219 220 return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< storage_type >(old_val), order)); 221 } 222 223 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) 224 225 private: compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const226 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) const BOOST_NOEXCEPT 227 { 228 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 229 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 230 #else 231 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 232 #endif 233 } 234 compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const235 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) const BOOST_NOEXCEPT 236 { 237 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); 238 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 239 expected = atomics::detail::bitwise_cast< value_type >(old_value); 240 return res; 241 } 242 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const243 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) const BOOST_NOEXCEPT 244 { 245 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 246 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 247 #else 248 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 249 #endif 250 } 251 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const252 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) const BOOST_NOEXCEPT 253 { 254 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); 255 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 256 expected = atomics::detail::bitwise_cast< value_type >(old_value); 257 return res; 258 } 259 }; 260 261 262 //! Implementation for integers 263 template< typename T, bool Interprocess > 264 class base_atomic_ref< T, int, Interprocess > : 265 public base_atomic_ref_common< T, atomics::detail::is_signed< T >::value, Interprocess > 266 { 267 private: 268 typedef base_atomic_ref_common< T, atomics::detail::is_signed< T >::value, Interprocess > base_type; 269 270 public: 271 typedef typename base_type::value_type value_type; 272 typedef typename base_type::value_type difference_type; 273 274 protected: 275 typedef typename base_type::core_operations core_operations; 276 typedef typename base_type::wait_operations wait_operations; 277 typedef atomics::detail::extra_operations< core_operations > extra_operations; 278 typedef typename base_type::storage_type storage_type; 279 typedef value_type value_arg_type; 280 281 private: 282 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast; 283 284 public: base_atomic_ref(base_atomic_ref const & that)285 BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) 286 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) 287 { 288 } 289 290 // Standard methods store(value_arg_type v,memory_order order=memory_order_seq_cst) const291 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 292 { 293 BOOST_ASSERT(order != memory_order_consume); 294 BOOST_ASSERT(order != memory_order_acquire); 295 BOOST_ASSERT(order != memory_order_acq_rel); 296 297 core_operations::store(this->storage(), static_cast< storage_type >(v), order); 298 } 299 load(memory_order order=memory_order_seq_cst) const300 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 301 { 302 BOOST_ASSERT(order != memory_order_release); 303 BOOST_ASSERT(order != memory_order_acq_rel); 304 305 return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); 306 } 307 fetch_add(difference_type v,memory_order order=memory_order_seq_cst) const308 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 309 { 310 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_add(this->storage(), static_cast< storage_type >(v), order)); 311 } 312 fetch_sub(difference_type v,memory_order order=memory_order_seq_cst) const313 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 314 { 315 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_sub(this->storage(), static_cast< storage_type >(v), order)); 316 } 317 exchange(value_arg_type v,memory_order order=memory_order_seq_cst) const318 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 319 { 320 return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), static_cast< storage_type >(v), order)); 321 } 322 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const323 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 324 { 325 BOOST_ASSERT(failure_order != memory_order_release); 326 BOOST_ASSERT(failure_order != memory_order_acq_rel); 327 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 328 329 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 330 } 331 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const332 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 333 { 334 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); 335 } 336 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const337 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 338 { 339 BOOST_ASSERT(failure_order != memory_order_release); 340 BOOST_ASSERT(failure_order != memory_order_acq_rel); 341 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 342 343 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 344 } 345 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const346 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 347 { 348 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); 349 } 350 fetch_and(value_arg_type v,memory_order order=memory_order_seq_cst) const351 BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 352 { 353 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_and(this->storage(), static_cast< storage_type >(v), order)); 354 } 355 fetch_or(value_arg_type v,memory_order order=memory_order_seq_cst) const356 BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 357 { 358 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_or(this->storage(), static_cast< storage_type >(v), order)); 359 } 360 fetch_xor(value_arg_type v,memory_order order=memory_order_seq_cst) const361 BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 362 { 363 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_xor(this->storage(), static_cast< storage_type >(v), order)); 364 } 365 366 // Boost.Atomic extensions fetch_negate(memory_order order=memory_order_seq_cst) const367 BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 368 { 369 return atomics::detail::bitwise_cast< value_type >(extra_operations::fetch_negate(this->storage(), order)); 370 } 371 fetch_complement(memory_order order=memory_order_seq_cst) const372 BOOST_FORCEINLINE value_type fetch_complement(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 373 { 374 return atomics::detail::bitwise_cast< value_type >(extra_operations::fetch_complement(this->storage(), order)); 375 } 376 add(difference_type v,memory_order order=memory_order_seq_cst) const377 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 378 { 379 return atomics::detail::bitwise_cast< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v), order)); 380 } 381 sub(difference_type v,memory_order order=memory_order_seq_cst) const382 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 383 { 384 return atomics::detail::bitwise_cast< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v), order)); 385 } 386 negate(memory_order order=memory_order_seq_cst) const387 BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 388 { 389 return atomics::detail::bitwise_cast< value_type >(extra_operations::negate(this->storage(), order)); 390 } 391 bitwise_and(value_arg_type v,memory_order order=memory_order_seq_cst) const392 BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 393 { 394 return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_and(this->storage(), static_cast< storage_type >(v), order)); 395 } 396 bitwise_or(value_arg_type v,memory_order order=memory_order_seq_cst) const397 BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 398 { 399 return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_or(this->storage(), static_cast< storage_type >(v), order)); 400 } 401 bitwise_xor(value_arg_type v,memory_order order=memory_order_seq_cst) const402 BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 403 { 404 return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_xor(this->storage(), static_cast< storage_type >(v), order)); 405 } 406 bitwise_complement(memory_order order=memory_order_seq_cst) const407 BOOST_FORCEINLINE value_type bitwise_complement(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 408 { 409 return atomics::detail::bitwise_cast< value_type >(extra_operations::bitwise_complement(this->storage(), order)); 410 } 411 opaque_add(difference_type v,memory_order order=memory_order_seq_cst) const412 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 413 { 414 extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v), order); 415 } 416 opaque_sub(difference_type v,memory_order order=memory_order_seq_cst) const417 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 418 { 419 extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v), order); 420 } 421 opaque_negate(memory_order order=memory_order_seq_cst) const422 BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 423 { 424 extra_operations::opaque_negate(this->storage(), order); 425 } 426 opaque_and(value_arg_type v,memory_order order=memory_order_seq_cst) const427 BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 428 { 429 extra_operations::opaque_and(this->storage(), static_cast< storage_type >(v), order); 430 } 431 opaque_or(value_arg_type v,memory_order order=memory_order_seq_cst) const432 BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 433 { 434 extra_operations::opaque_or(this->storage(), static_cast< storage_type >(v), order); 435 } 436 opaque_xor(value_arg_type v,memory_order order=memory_order_seq_cst) const437 BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 438 { 439 extra_operations::opaque_xor(this->storage(), static_cast< storage_type >(v), order); 440 } 441 opaque_complement(memory_order order=memory_order_seq_cst) const442 BOOST_FORCEINLINE void opaque_complement(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 443 { 444 extra_operations::opaque_complement(this->storage(), order); 445 } 446 add_and_test(difference_type v,memory_order order=memory_order_seq_cst) const447 BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 448 { 449 return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order); 450 } 451 sub_and_test(difference_type v,memory_order order=memory_order_seq_cst) const452 BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 453 { 454 return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order); 455 } 456 negate_and_test(memory_order order=memory_order_seq_cst) const457 BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 458 { 459 return extra_operations::negate_and_test(this->storage(), order); 460 } 461 and_and_test(value_arg_type v,memory_order order=memory_order_seq_cst) const462 BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 463 { 464 return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order); 465 } 466 or_and_test(value_arg_type v,memory_order order=memory_order_seq_cst) const467 BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 468 { 469 return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order); 470 } 471 xor_and_test(value_arg_type v,memory_order order=memory_order_seq_cst) const472 BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 473 { 474 return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order); 475 } 476 complement_and_test(memory_order order=memory_order_seq_cst) const477 BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 478 { 479 return extra_operations::complement_and_test(this->storage(), order); 480 } 481 bit_test_and_set(unsigned int bit_number,memory_order order=memory_order_seq_cst) const482 BOOST_FORCEINLINE bool bit_test_and_set(unsigned int bit_number, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 483 { 484 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); 485 return extra_operations::bit_test_and_set(this->storage(), bit_number, order); 486 } 487 bit_test_and_reset(unsigned int bit_number,memory_order order=memory_order_seq_cst) const488 BOOST_FORCEINLINE bool bit_test_and_reset(unsigned int bit_number, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 489 { 490 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); 491 return extra_operations::bit_test_and_reset(this->storage(), bit_number, order); 492 } 493 bit_test_and_complement(unsigned int bit_number,memory_order order=memory_order_seq_cst) const494 BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 495 { 496 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); 497 return extra_operations::bit_test_and_complement(this->storage(), bit_number, order); 498 } 499 500 // Operators operator ++(int) const501 BOOST_FORCEINLINE value_type operator++(int) const BOOST_NOEXCEPT 502 { 503 return fetch_add(1); 504 } 505 operator ++() const506 BOOST_FORCEINLINE value_type operator++() const BOOST_NOEXCEPT 507 { 508 return add(1); 509 } 510 operator --(int) const511 BOOST_FORCEINLINE value_type operator--(int) const BOOST_NOEXCEPT 512 { 513 return fetch_sub(1); 514 } 515 operator --() const516 BOOST_FORCEINLINE value_type operator--() const BOOST_NOEXCEPT 517 { 518 return sub(1); 519 } 520 operator +=(difference_type v) const521 BOOST_FORCEINLINE value_type operator+=(difference_type v) const BOOST_NOEXCEPT 522 { 523 return add(v); 524 } 525 operator -=(difference_type v) const526 BOOST_FORCEINLINE value_type operator-=(difference_type v) const BOOST_NOEXCEPT 527 { 528 return sub(v); 529 } 530 operator &=(value_type v) const531 BOOST_FORCEINLINE value_type operator&=(value_type v) const BOOST_NOEXCEPT 532 { 533 return bitwise_and(v); 534 } 535 operator |=(value_type v) const536 BOOST_FORCEINLINE value_type operator|=(value_type v) const BOOST_NOEXCEPT 537 { 538 return bitwise_or(v); 539 } 540 operator ^=(value_type v) const541 BOOST_FORCEINLINE value_type operator^=(value_type v) const BOOST_NOEXCEPT 542 { 543 return bitwise_xor(v); 544 } 545 wait(value_arg_type old_val,memory_order order=memory_order_seq_cst) const546 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 547 { 548 BOOST_ASSERT(order != memory_order_release); 549 BOOST_ASSERT(order != memory_order_acq_rel); 550 551 return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order)); 552 } 553 554 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) 555 556 private: compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const557 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) const BOOST_NOEXCEPT 558 { 559 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 560 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); 561 #else 562 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 563 #endif 564 } 565 compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const566 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) const BOOST_NOEXCEPT 567 { 568 storage_type old_value = static_cast< storage_type >(expected); 569 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); 570 expected = atomics::detail::bitwise_cast< value_type >(old_value); 571 return res; 572 } 573 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const574 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) const BOOST_NOEXCEPT 575 { 576 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 577 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); 578 #else 579 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 580 #endif 581 } 582 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const583 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) const BOOST_NOEXCEPT 584 { 585 storage_type old_value = static_cast< storage_type >(expected); 586 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); 587 expected = atomics::detail::bitwise_cast< value_type >(old_value); 588 return res; 589 } 590 }; 591 592 //! Implementation for bool 593 template< bool Interprocess > 594 class base_atomic_ref< bool, int, Interprocess > : 595 public base_atomic_ref_common< bool, false, Interprocess > 596 { 597 private: 598 typedef base_atomic_ref_common< bool, false, Interprocess > base_type; 599 600 public: 601 typedef bool value_type; 602 603 protected: 604 typedef typename base_type::core_operations core_operations; 605 typedef typename base_type::wait_operations wait_operations; 606 typedef typename base_type::storage_type storage_type; 607 typedef value_type value_arg_type; 608 609 private: 610 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast; 611 612 public: base_atomic_ref(base_atomic_ref const & that)613 BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) 614 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) 615 { 616 } 617 618 // Standard methods store(value_arg_type v,memory_order order=memory_order_seq_cst) const619 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 620 { 621 BOOST_ASSERT(order != memory_order_consume); 622 BOOST_ASSERT(order != memory_order_acquire); 623 BOOST_ASSERT(order != memory_order_acq_rel); 624 625 core_operations::store(this->storage(), static_cast< storage_type >(v), order); 626 } 627 load(memory_order order=memory_order_seq_cst) const628 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 629 { 630 BOOST_ASSERT(order != memory_order_release); 631 BOOST_ASSERT(order != memory_order_acq_rel); 632 633 return !!core_operations::load(this->storage(), order); 634 } 635 exchange(value_arg_type v,memory_order order=memory_order_seq_cst) const636 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 637 { 638 return !!core_operations::exchange(this->storage(), static_cast< storage_type >(v), order); 639 } 640 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const641 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 642 { 643 BOOST_ASSERT(failure_order != memory_order_release); 644 BOOST_ASSERT(failure_order != memory_order_acq_rel); 645 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 646 647 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 648 } 649 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const650 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 651 { 652 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); 653 } 654 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const655 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 656 { 657 BOOST_ASSERT(failure_order != memory_order_release); 658 BOOST_ASSERT(failure_order != memory_order_acq_rel); 659 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 660 661 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 662 } 663 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const664 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 665 { 666 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); 667 } 668 wait(value_arg_type old_val,memory_order order=memory_order_seq_cst) const669 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 670 { 671 BOOST_ASSERT(order != memory_order_release); 672 BOOST_ASSERT(order != memory_order_acq_rel); 673 674 return !!wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order); 675 } 676 677 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) 678 679 private: compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const680 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) const BOOST_NOEXCEPT 681 { 682 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 683 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); 684 #else 685 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 686 #endif 687 } 688 compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const689 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) const BOOST_NOEXCEPT 690 { 691 storage_type old_value = static_cast< storage_type >(expected); 692 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); 693 expected = !!old_value; 694 return res; 695 } 696 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const697 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) const BOOST_NOEXCEPT 698 { 699 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 700 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); 701 #else 702 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 703 #endif 704 } 705 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const706 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) const BOOST_NOEXCEPT 707 { 708 storage_type old_value = static_cast< storage_type >(expected); 709 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); 710 expected = !!old_value; 711 return res; 712 } 713 }; 714 715 716 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT) 717 718 //! Implementation for floating point types 719 template< typename T, bool Interprocess > 720 class base_atomic_ref< T, float, Interprocess > : 721 public base_atomic_ref_common< T, false, Interprocess > 722 { 723 private: 724 typedef base_atomic_ref_common< T, false, Interprocess > base_type; 725 726 public: 727 typedef typename base_type::value_type value_type; 728 typedef typename base_type::value_type difference_type; 729 730 protected: 731 typedef typename base_type::core_operations core_operations; 732 typedef typename base_type::wait_operations wait_operations; 733 typedef atomics::detail::extra_operations< core_operations > extra_operations; 734 typedef atomics::detail::fp_operations< extra_operations, value_type > fp_operations; 735 typedef atomics::detail::extra_fp_operations< fp_operations > extra_fp_operations; 736 typedef typename base_type::storage_type storage_type; 737 typedef value_type value_arg_type; 738 739 private: 740 typedef atomics::detail::integral_constant< bool, atomics::detail::value_sizeof< value_type >::value != sizeof(storage_type) > has_padding_bits; 741 typedef atomics::detail::integral_constant< bool, has_padding_bits::value || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast; 742 743 public: base_atomic_ref(base_atomic_ref const & that)744 BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) 745 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) 746 { 747 this->clear_padding_bits(has_padding_bits()); 748 } 749 store(value_arg_type v,memory_order order=memory_order_seq_cst) const750 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 751 { 752 BOOST_ASSERT(order != memory_order_consume); 753 BOOST_ASSERT(order != memory_order_acquire); 754 BOOST_ASSERT(order != memory_order_acq_rel); 755 756 core_operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order); 757 } 758 load(memory_order order=memory_order_seq_cst) const759 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 760 { 761 BOOST_ASSERT(order != memory_order_release); 762 BOOST_ASSERT(order != memory_order_acq_rel); 763 764 return atomics::detail::bitwise_fp_cast< value_type >(core_operations::load(this->storage(), order)); 765 } 766 fetch_add(difference_type v,memory_order order=memory_order_seq_cst) const767 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 768 { 769 return fp_operations::fetch_add(this->storage(), v, order); 770 } 771 fetch_sub(difference_type v,memory_order order=memory_order_seq_cst) const772 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 773 { 774 return fp_operations::fetch_sub(this->storage(), v, order); 775 } 776 exchange(value_arg_type v,memory_order order=memory_order_seq_cst) const777 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 778 { 779 return atomics::detail::bitwise_fp_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order)); 780 } 781 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const782 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 783 { 784 BOOST_ASSERT(failure_order != memory_order_release); 785 BOOST_ASSERT(failure_order != memory_order_acq_rel); 786 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 787 788 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 789 } 790 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const791 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 792 { 793 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); 794 } 795 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const796 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 797 { 798 BOOST_ASSERT(failure_order != memory_order_release); 799 BOOST_ASSERT(failure_order != memory_order_acq_rel); 800 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 801 802 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 803 } 804 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const805 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 806 { 807 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); 808 } 809 810 // Boost.Atomic extensions fetch_negate(memory_order order=memory_order_seq_cst) const811 BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 812 { 813 return extra_fp_operations::fetch_negate(this->storage(), order); 814 } 815 add(difference_type v,memory_order order=memory_order_seq_cst) const816 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 817 { 818 return extra_fp_operations::add(this->storage(), v, order); 819 } 820 sub(difference_type v,memory_order order=memory_order_seq_cst) const821 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 822 { 823 return extra_fp_operations::sub(this->storage(), v, order); 824 } 825 negate(memory_order order=memory_order_seq_cst) const826 BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 827 { 828 return extra_fp_operations::negate(this->storage(), order); 829 } 830 opaque_add(difference_type v,memory_order order=memory_order_seq_cst) const831 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 832 { 833 extra_fp_operations::opaque_add(this->storage(), v, order); 834 } 835 opaque_sub(difference_type v,memory_order order=memory_order_seq_cst) const836 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 837 { 838 extra_fp_operations::opaque_sub(this->storage(), v, order); 839 } 840 opaque_negate(memory_order order=memory_order_seq_cst) const841 BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 842 { 843 extra_fp_operations::opaque_negate(this->storage(), order); 844 } 845 846 // Operators operator +=(difference_type v) const847 BOOST_FORCEINLINE value_type operator+=(difference_type v) const BOOST_NOEXCEPT 848 { 849 return add(v); 850 } 851 operator -=(difference_type v) const852 BOOST_FORCEINLINE value_type operator-=(difference_type v) const BOOST_NOEXCEPT 853 { 854 return sub(v); 855 } 856 wait(value_arg_type old_val,memory_order order=memory_order_seq_cst) const857 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 858 { 859 BOOST_ASSERT(order != memory_order_release); 860 BOOST_ASSERT(order != memory_order_acq_rel); 861 862 return atomics::detail::bitwise_fp_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(old_val), order)); 863 } 864 865 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) 866 867 private: clear_padding_bits(atomics::detail::false_type) const868 BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::false_type) const BOOST_NOEXCEPT 869 { 870 } 871 clear_padding_bits(atomics::detail::true_type) const872 BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::true_type) const BOOST_NOEXCEPT 873 { 874 storage_type old_value = core_operations::load(this->storage(), boost::memory_order_relaxed); 875 while (true) 876 { 877 storage_type new_value = old_value; 878 atomics::detail::clear_tail_padding_bits< atomics::detail::value_sizeof< value_type >::value >(new_value); 879 bool res = core_operations::compare_exchange_weak(this->storage(), old_value, new_value, boost::memory_order_relaxed, boost::memory_order_relaxed); 880 if (BOOST_LIKELY(res)) 881 break; 882 } 883 } 884 compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const885 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) const BOOST_NOEXCEPT 886 { 887 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 888 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); 889 #else 890 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 891 #endif 892 } 893 compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const894 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) const BOOST_NOEXCEPT 895 { 896 storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); 897 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); 898 expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); 899 return res; 900 } 901 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const902 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) const BOOST_NOEXCEPT 903 { 904 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 905 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); 906 #else 907 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 908 #endif 909 } 910 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const911 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) const BOOST_NOEXCEPT 912 { 913 storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); 914 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order); 915 expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); 916 return res; 917 } 918 }; 919 920 #endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT) 921 922 923 //! Implementation for pointers to object types 924 template< typename T, bool Interprocess > 925 class base_atomic_ref< T*, void*, Interprocess > : 926 public base_atomic_ref_common< T*, false, Interprocess > 927 { 928 private: 929 typedef base_atomic_ref_common< T*, false, Interprocess > base_type; 930 931 public: 932 typedef typename base_type::value_type value_type; 933 typedef std::ptrdiff_t difference_type; 934 935 protected: 936 typedef typename base_type::core_operations core_operations; 937 typedef typename base_type::wait_operations wait_operations; 938 typedef atomics::detail::extra_operations< core_operations > extra_operations; 939 typedef typename base_type::storage_type storage_type; 940 typedef value_type value_arg_type; 941 942 private: 943 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast; 944 945 public: base_atomic_ref(base_atomic_ref const & that)946 BOOST_DEFAULTED_FUNCTION(base_atomic_ref(base_atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {}) 947 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v) 948 { 949 } 950 951 // Standard methods store(value_arg_type v,memory_order order=memory_order_seq_cst) const952 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 953 { 954 BOOST_ASSERT(order != memory_order_consume); 955 BOOST_ASSERT(order != memory_order_acquire); 956 BOOST_ASSERT(order != memory_order_acq_rel); 957 958 core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order); 959 } 960 load(memory_order order=memory_order_seq_cst) const961 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 962 { 963 BOOST_ASSERT(order != memory_order_release); 964 BOOST_ASSERT(order != memory_order_acq_rel); 965 966 return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); 967 } 968 fetch_add(difference_type v,memory_order order=memory_order_seq_cst) const969 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 970 { 971 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_add(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); 972 } 973 fetch_sub(difference_type v,memory_order order=memory_order_seq_cst) const974 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 975 { 976 return atomics::detail::bitwise_cast< value_type >(core_operations::fetch_sub(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); 977 } 978 exchange(value_type v,memory_order order=memory_order_seq_cst) const979 BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 980 { 981 return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order)); 982 } 983 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const984 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 985 { 986 BOOST_ASSERT(failure_order != memory_order_release); 987 BOOST_ASSERT(failure_order != memory_order_acq_rel); 988 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 989 990 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 991 } 992 compare_exchange_strong(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const993 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 994 { 995 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); 996 } 997 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order) const998 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT 999 { 1000 BOOST_ASSERT(failure_order != memory_order_release); 1001 BOOST_ASSERT(failure_order != memory_order_acq_rel); 1002 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order)); 1003 1004 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast()); 1005 } 1006 compare_exchange_weak(value_type & expected,value_arg_type desired,memory_order order=memory_order_seq_cst) const1007 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1008 { 1009 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); 1010 } 1011 1012 // Boost.Atomic extensions add(difference_type v,memory_order order=memory_order_seq_cst) const1013 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1014 { 1015 return atomics::detail::bitwise_cast< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); 1016 } 1017 sub(difference_type v,memory_order order=memory_order_seq_cst) const1018 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1019 { 1020 return atomics::detail::bitwise_cast< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v * sizeof(T)), order)); 1021 } 1022 opaque_add(difference_type v,memory_order order=memory_order_seq_cst) const1023 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1024 { 1025 extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); 1026 } 1027 opaque_sub(difference_type v,memory_order order=memory_order_seq_cst) const1028 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1029 { 1030 extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); 1031 } 1032 add_and_test(difference_type v,memory_order order=memory_order_seq_cst) const1033 BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1034 { 1035 return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); 1036 } 1037 sub_and_test(difference_type v,memory_order order=memory_order_seq_cst) const1038 BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1039 { 1040 return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v * sizeof(T)), order); 1041 } 1042 1043 // Operators operator ++(int) const1044 BOOST_FORCEINLINE value_type operator++(int) const BOOST_NOEXCEPT 1045 { 1046 return fetch_add(1); 1047 } 1048 operator ++() const1049 BOOST_FORCEINLINE value_type operator++() const BOOST_NOEXCEPT 1050 { 1051 return add(1); 1052 } 1053 operator --(int) const1054 BOOST_FORCEINLINE value_type operator--(int) const BOOST_NOEXCEPT 1055 { 1056 return fetch_sub(1); 1057 } 1058 operator --() const1059 BOOST_FORCEINLINE value_type operator--() const BOOST_NOEXCEPT 1060 { 1061 return sub(1); 1062 } 1063 operator +=(difference_type v) const1064 BOOST_FORCEINLINE value_type operator+=(difference_type v) const BOOST_NOEXCEPT 1065 { 1066 return add(v); 1067 } 1068 operator -=(difference_type v) const1069 BOOST_FORCEINLINE value_type operator-=(difference_type v) const BOOST_NOEXCEPT 1070 { 1071 return sub(v); 1072 } 1073 wait(value_arg_type old_val,memory_order order=memory_order_seq_cst) const1074 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT 1075 { 1076 BOOST_ASSERT(order != memory_order_release); 1077 BOOST_ASSERT(order != memory_order_acq_rel); 1078 1079 return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< storage_type >(old_val), order)); 1080 } 1081 1082 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&)) 1083 1084 private: compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const1085 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) const BOOST_NOEXCEPT 1086 { 1087 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 1088 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 1089 #else 1090 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 1091 #endif 1092 } 1093 compare_exchange_strong_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const1094 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) const BOOST_NOEXCEPT 1095 { 1096 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); 1097 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 1098 expected = atomics::detail::bitwise_cast< value_type >(old_value); 1099 return res; 1100 } 1101 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::false_type) const1102 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) const BOOST_NOEXCEPT 1103 { 1104 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS) 1105 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 1106 #else 1107 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type()); 1108 #endif 1109 } 1110 compare_exchange_weak_impl(value_type & expected,value_arg_type desired,memory_order success_order,memory_order failure_order,atomics::detail::true_type) const1111 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) const BOOST_NOEXCEPT 1112 { 1113 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); 1114 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); 1115 expected = atomics::detail::bitwise_cast< value_type >(old_value); 1116 return res; 1117 } 1118 }; 1119 1120 } // namespace detail 1121 } // namespace atomics 1122 } // namespace boost 1123 1124 #include <boost/atomic/detail/footer.hpp> 1125 1126 #endif // BOOST_ATOMIC_DETAIL_ATOMIC_REF_IMPL_HPP_INCLUDED_ 1127