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