]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/atomic/detail/atomic_ref_template.hpp
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / boost / boost / atomic / detail / atomic_ref_template.hpp
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_template.hpp
10 *
11 * This header contains interface definition of \c atomic_ref template.
12 */
13
14 #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_REF_TEMPLATE_HPP_INCLUDED_
15 #define BOOST_ATOMIC_DETAIL_ATOMIC_REF_TEMPLATE_HPP_INCLUDED_
16
17 #include <cstddef>
18 #include <boost/cstdint.hpp>
19 #include <boost/assert.hpp>
20 #include <boost/static_assert.hpp>
21 #include <boost/memory_order.hpp>
22 #include <boost/atomic/detail/config.hpp>
23 #include <boost/atomic/detail/intptr.hpp>
24 #include <boost/atomic/detail/classify.hpp>
25 #include <boost/atomic/detail/addressof.hpp>
26 #include <boost/atomic/detail/storage_traits.hpp>
27 #include <boost/atomic/detail/bitwise_cast.hpp>
28 #include <boost/atomic/detail/integral_conversions.hpp>
29 #include <boost/atomic/detail/operations.hpp>
30 #include <boost/atomic/detail/extra_operations.hpp>
31 #include <boost/atomic/detail/memory_order_utils.hpp>
32 #include <boost/atomic/detail/type_traits/is_signed.hpp>
33 #include <boost/atomic/detail/type_traits/is_trivially_copyable.hpp>
34 #include <boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp>
35 #include <boost/atomic/detail/type_traits/alignment_of.hpp>
36 #include <boost/atomic/detail/type_traits/conditional.hpp>
37 #include <boost/atomic/detail/type_traits/integral_constant.hpp>
38 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
39 #include <boost/atomic/detail/bitwise_fp_cast.hpp>
40 #include <boost/atomic/detail/fp_operations.hpp>
41 #include <boost/atomic/detail/extra_fp_operations.hpp>
42 #endif
43
44 #ifdef BOOST_HAS_PRAGMA_ONCE
45 #pragma once
46 #endif
47
48 #if defined(BOOST_MSVC)
49 #pragma warning(push)
50 // 'boost::atomics::atomic_ref<T>' : multiple assignment operators specified
51 #pragma warning(disable: 4522)
52 #endif
53
54 /*
55 * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
56 * see comment for convert_memory_order_to_gcc in ops_gcc_atomic.hpp.
57 */
58
59 namespace boost {
60 namespace atomics {
61 namespace detail {
62
63 template< typename T, bool IsSigned >
64 struct is_atomic_ref_lock_free
65 {
66 typedef T value_type;
67 typedef atomics::detail::operations< sizeof(value_type), IsSigned > operations;
68 typedef typename operations::storage_type storage_type;
69
70 static BOOST_CONSTEXPR_OR_CONST bool value = sizeof(value_type) == sizeof(storage_type) && operations::is_always_lock_free;
71 };
72
73 template< typename T, bool IsSigned >
74 class base_atomic_ref_common
75 {
76 public:
77 typedef T value_type;
78
79 protected:
80 typedef typename atomics::detail::conditional<
81 atomics::detail::is_atomic_ref_lock_free< T, IsSigned >::value,
82 atomics::detail::operations< sizeof(value_type), IsSigned >,
83 atomics::detail::emulated_operations< sizeof(value_type), atomics::detail::alignment_of< value_type >::value, IsSigned >
84 >::type operations;
85 typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type;
86 typedef typename operations::storage_type storage_type;
87
88 public:
89 static BOOST_CONSTEXPR_OR_CONST std::size_t required_alignment = atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment ? operations::storage_alignment : atomics::detail::alignment_of< value_type >::value;
90 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = operations::is_always_lock_free;
91
92 protected:
93 value_type* m_value;
94
95 public:
96 BOOST_FORCEINLINE explicit base_atomic_ref_common(value_type& v) BOOST_NOEXCEPT : m_value(atomics::detail::addressof(v))
97 {
98 }
99
100 protected:
101 BOOST_FORCEINLINE storage_type& storage() const BOOST_NOEXCEPT
102 {
103 return *reinterpret_cast< storage_type* >(m_value);
104 }
105 };
106
107 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
108 template< typename T, bool IsSigned >
109 BOOST_CONSTEXPR_OR_CONST std::size_t base_atomic_ref_common< T, IsSigned >::required_alignment;
110 template< typename T, bool IsSigned >
111 BOOST_CONSTEXPR_OR_CONST bool base_atomic_ref_common< T, IsSigned >::is_always_lock_free;
112 #endif
113
114
115 template< typename T, typename Kind >
116 class base_atomic_ref;
117
118 //! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types
119 template< typename T >
120 class base_atomic_ref< T, void > :
121 public base_atomic_ref_common< T, false >
122 {
123 private:
124 typedef base_atomic_ref_common< T, false > base_type;
125
126 public:
127 typedef typename base_type::value_type value_type;
128
129 protected:
130 typedef typename base_type::operations operations;
131 typedef typename base_type::storage_type storage_type;
132 typedef typename base_type::value_arg_type value_arg_type;
133
134 private:
135 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
136
137 public:
138 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)) {})
139 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
140 {
141 }
142
143 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
144 {
145 BOOST_ASSERT(order != memory_order_consume);
146 BOOST_ASSERT(order != memory_order_acquire);
147 BOOST_ASSERT(order != memory_order_acq_rel);
148
149 operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order);
150 }
151
152 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
153 {
154 BOOST_ASSERT(order != memory_order_release);
155 BOOST_ASSERT(order != memory_order_acq_rel);
156
157 return atomics::detail::bitwise_cast< value_type >(operations::load(this->storage(), order));
158 }
159
160 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
161 {
162 return atomics::detail::bitwise_cast< value_type >(operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order));
163 }
164
165 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT
166 {
167 BOOST_ASSERT(failure_order != memory_order_release);
168 BOOST_ASSERT(failure_order != memory_order_acq_rel);
169 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
170
171 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
172 }
173
174 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
175 {
176 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
177 }
178
179 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) const BOOST_NOEXCEPT
180 {
181 BOOST_ASSERT(failure_order != memory_order_release);
182 BOOST_ASSERT(failure_order != memory_order_acq_rel);
183 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
184
185 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
186 }
187
188 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
189 {
190 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
191 }
192
193 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
194
195 private:
196 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
197 {
198 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
199 return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
200 #else
201 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
202 #endif
203 }
204
205 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
206 {
207 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
208 const bool res = operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
209 expected = atomics::detail::bitwise_cast< value_type >(old_value);
210 return res;
211 }
212
213 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
214 {
215 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
216 return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
217 #else
218 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
219 #endif
220 }
221
222 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
223 {
224 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
225 const bool res = operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order);
226 expected = atomics::detail::bitwise_cast< value_type >(old_value);
227 return res;
228 }
229 };
230
231
232 //! Implementation for integers
233 template< typename T >
234 class base_atomic_ref< T, int > :
235 public base_atomic_ref_common< T, atomics::detail::is_signed< T >::value >
236 {
237 private:
238 typedef base_atomic_ref_common< T, atomics::detail::is_signed< T >::value > base_type;
239
240 public:
241 typedef typename base_type::value_type value_type;
242 typedef typename base_type::value_type difference_type;
243
244 protected:
245 typedef typename base_type::operations operations;
246 typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
247 typedef typename base_type::storage_type storage_type;
248 typedef value_type value_arg_type;
249
250 private:
251 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
252
253 public:
254 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)) {})
255 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
256 {
257 }
258
259 // Standard methods
260 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
261 {
262 BOOST_ASSERT(order != memory_order_consume);
263 BOOST_ASSERT(order != memory_order_acquire);
264 BOOST_ASSERT(order != memory_order_acq_rel);
265
266 operations::store(this->storage(), static_cast< storage_type >(v), order);
267 }
268
269 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
270 {
271 BOOST_ASSERT(order != memory_order_release);
272 BOOST_ASSERT(order != memory_order_acq_rel);
273
274 return atomics::detail::integral_truncate< value_type >(operations::load(this->storage(), order));
275 }
276
277 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
278 {
279 return atomics::detail::integral_truncate< value_type >(operations::fetch_add(this->storage(), static_cast< storage_type >(v), order));
280 }
281
282 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
283 {
284 return atomics::detail::integral_truncate< value_type >(operations::fetch_sub(this->storage(), static_cast< storage_type >(v), order));
285 }
286
287 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
288 {
289 return atomics::detail::integral_truncate< value_type >(operations::exchange(this->storage(), static_cast< storage_type >(v), order));
290 }
291
292 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
293 {
294 BOOST_ASSERT(failure_order != memory_order_release);
295 BOOST_ASSERT(failure_order != memory_order_acq_rel);
296 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
297
298 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
299 }
300
301 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
302 {
303 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
304 }
305
306 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
307 {
308 BOOST_ASSERT(failure_order != memory_order_release);
309 BOOST_ASSERT(failure_order != memory_order_acq_rel);
310 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
311
312 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
313 }
314
315 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
316 {
317 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
318 }
319
320 BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
321 {
322 return atomics::detail::integral_truncate< value_type >(operations::fetch_and(this->storage(), static_cast< storage_type >(v), order));
323 }
324
325 BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
326 {
327 return atomics::detail::integral_truncate< value_type >(operations::fetch_or(this->storage(), static_cast< storage_type >(v), order));
328 }
329
330 BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
331 {
332 return atomics::detail::integral_truncate< value_type >(operations::fetch_xor(this->storage(), static_cast< storage_type >(v), order));
333 }
334
335 // Boost.Atomic extensions
336 BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
337 {
338 return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_negate(this->storage(), order));
339 }
340
341 BOOST_FORCEINLINE value_type fetch_complement(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
342 {
343 return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_complement(this->storage(), order));
344 }
345
346 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
347 {
348 return atomics::detail::integral_truncate< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v), order));
349 }
350
351 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
352 {
353 return atomics::detail::integral_truncate< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v), order));
354 }
355
356 BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
357 {
358 return atomics::detail::integral_truncate< value_type >(extra_operations::negate(this->storage(), order));
359 }
360
361 BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
362 {
363 return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_and(this->storage(), static_cast< storage_type >(v), order));
364 }
365
366 BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
367 {
368 return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_or(this->storage(), static_cast< storage_type >(v), order));
369 }
370
371 BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
372 {
373 return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_xor(this->storage(), static_cast< storage_type >(v), order));
374 }
375
376 BOOST_FORCEINLINE value_type bitwise_complement(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
377 {
378 return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_complement(this->storage(), order));
379 }
380
381 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
382 {
383 extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v), order);
384 }
385
386 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
387 {
388 extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v), order);
389 }
390
391 BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
392 {
393 extra_operations::opaque_negate(this->storage(), order);
394 }
395
396 BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
397 {
398 extra_operations::opaque_and(this->storage(), static_cast< storage_type >(v), order);
399 }
400
401 BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
402 {
403 extra_operations::opaque_or(this->storage(), static_cast< storage_type >(v), order);
404 }
405
406 BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
407 {
408 extra_operations::opaque_xor(this->storage(), static_cast< storage_type >(v), order);
409 }
410
411 BOOST_FORCEINLINE void opaque_complement(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
412 {
413 extra_operations::opaque_complement(this->storage(), order);
414 }
415
416 BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
417 {
418 return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order);
419 }
420
421 BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
422 {
423 return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order);
424 }
425
426 BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
427 {
428 return extra_operations::negate_and_test(this->storage(), order);
429 }
430
431 BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
432 {
433 return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order);
434 }
435
436 BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
437 {
438 return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order);
439 }
440
441 BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
442 {
443 return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order);
444 }
445
446 BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
447 {
448 return extra_operations::complement_and_test(this->storage(), order);
449 }
450
451 BOOST_FORCEINLINE bool bit_test_and_set(unsigned int bit_number, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
452 {
453 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
454 return extra_operations::bit_test_and_set(this->storage(), bit_number, order);
455 }
456
457 BOOST_FORCEINLINE bool bit_test_and_reset(unsigned int bit_number, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
458 {
459 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
460 return extra_operations::bit_test_and_reset(this->storage(), bit_number, order);
461 }
462
463 BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
464 {
465 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
466 return extra_operations::bit_test_and_complement(this->storage(), bit_number, order);
467 }
468
469 // Operators
470 BOOST_FORCEINLINE value_type operator++(int) BOOST_NOEXCEPT
471 {
472 return fetch_add(1);
473 }
474
475 BOOST_FORCEINLINE value_type operator++() BOOST_NOEXCEPT
476 {
477 return add(1);
478 }
479
480 BOOST_FORCEINLINE value_type operator--(int) BOOST_NOEXCEPT
481 {
482 return fetch_sub(1);
483 }
484
485 BOOST_FORCEINLINE value_type operator--() BOOST_NOEXCEPT
486 {
487 return sub(1);
488 }
489
490 BOOST_FORCEINLINE value_type operator+=(difference_type v) BOOST_NOEXCEPT
491 {
492 return add(v);
493 }
494
495 BOOST_FORCEINLINE value_type operator-=(difference_type v) BOOST_NOEXCEPT
496 {
497 return sub(v);
498 }
499
500 BOOST_FORCEINLINE value_type operator&=(value_type v) BOOST_NOEXCEPT
501 {
502 return bitwise_and(v);
503 }
504
505 BOOST_FORCEINLINE value_type operator|=(value_type v) BOOST_NOEXCEPT
506 {
507 return bitwise_or(v);
508 }
509
510 BOOST_FORCEINLINE value_type operator^=(value_type v) BOOST_NOEXCEPT
511 {
512 return bitwise_xor(v);
513 }
514
515 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
516
517 private:
518 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
519 {
520 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
521 return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
522 #else
523 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
524 #endif
525 }
526
527 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
528 {
529 storage_type old_value = static_cast< storage_type >(expected);
530 const bool res = operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
531 expected = atomics::detail::integral_truncate< value_type >(old_value);
532 return res;
533 }
534
535 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
536 {
537 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
538 return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
539 #else
540 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
541 #endif
542 }
543
544 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
545 {
546 storage_type old_value = static_cast< storage_type >(expected);
547 const bool res = operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
548 expected = atomics::detail::integral_truncate< value_type >(old_value);
549 return res;
550 }
551 };
552
553 //! Implementation for bool
554 template< >
555 class base_atomic_ref< bool, int > :
556 public base_atomic_ref_common< bool, false >
557 {
558 private:
559 typedef base_atomic_ref_common< bool, false > base_type;
560
561 public:
562 typedef bool value_type;
563
564 protected:
565 typedef base_type::operations operations;
566 typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
567 typedef base_type::storage_type storage_type;
568 typedef value_type value_arg_type;
569
570 private:
571 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
572
573 public:
574 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)) {})
575 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
576 {
577 }
578
579 // Standard methods
580 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
581 {
582 BOOST_ASSERT(order != memory_order_consume);
583 BOOST_ASSERT(order != memory_order_acquire);
584 BOOST_ASSERT(order != memory_order_acq_rel);
585
586 operations::store(this->storage(), static_cast< storage_type >(v), order);
587 }
588
589 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
590 {
591 BOOST_ASSERT(order != memory_order_release);
592 BOOST_ASSERT(order != memory_order_acq_rel);
593
594 return !!operations::load(this->storage(), order);
595 }
596
597 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
598 {
599 return !!operations::exchange(this->storage(), static_cast< storage_type >(v), order);
600 }
601
602 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
603 {
604 BOOST_ASSERT(failure_order != memory_order_release);
605 BOOST_ASSERT(failure_order != memory_order_acq_rel);
606 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
607
608 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
609 }
610
611 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
612 {
613 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
614 }
615
616 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
617 {
618 BOOST_ASSERT(failure_order != memory_order_release);
619 BOOST_ASSERT(failure_order != memory_order_acq_rel);
620 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
621
622 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
623 }
624
625 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
626 {
627 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
628 }
629
630 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
631
632 private:
633 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
634 {
635 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
636 return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
637 #else
638 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
639 #endif
640 }
641
642 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
643 {
644 storage_type old_value = static_cast< storage_type >(expected);
645 const bool res = operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
646 expected = !!old_value;
647 return res;
648 }
649
650 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
651 {
652 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
653 return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
654 #else
655 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
656 #endif
657 }
658
659 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
660 {
661 storage_type old_value = static_cast< storage_type >(expected);
662 const bool res = operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
663 expected = !!old_value;
664 return res;
665 }
666 };
667
668
669 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
670
671 //! Implementation for floating point types
672 template< typename T >
673 class base_atomic_ref< T, float > :
674 public base_atomic_ref_common< T, false >
675 {
676 private:
677 typedef base_atomic_ref_common< T, false > base_type;
678
679 public:
680 typedef typename base_type::value_type value_type;
681 typedef typename base_type::value_type difference_type;
682
683 protected:
684 typedef typename base_type::operations operations;
685 typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
686 typedef atomics::detail::fp_operations< extra_operations, value_type, operations::storage_size > fp_operations;
687 typedef atomics::detail::extra_fp_operations< fp_operations, value_type, operations::storage_size > extra_fp_operations;
688 typedef typename base_type::storage_type storage_type;
689 typedef value_type value_arg_type;
690
691 private:
692 typedef atomics::detail::integral_constant< bool, atomics::detail::value_sizeof< value_type >::value != sizeof(storage_type) > has_padding_bits;
693 typedef atomics::detail::integral_constant< bool, has_padding_bits::value || atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
694
695 public:
696 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)) {})
697 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
698 {
699 this->clear_padding_bits(has_padding_bits());
700 }
701
702 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
703 {
704 BOOST_ASSERT(order != memory_order_consume);
705 BOOST_ASSERT(order != memory_order_acquire);
706 BOOST_ASSERT(order != memory_order_acq_rel);
707
708 operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order);
709 }
710
711 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
712 {
713 BOOST_ASSERT(order != memory_order_release);
714 BOOST_ASSERT(order != memory_order_acq_rel);
715
716 return atomics::detail::bitwise_fp_cast< value_type >(operations::load(this->storage(), order));
717 }
718
719 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
720 {
721 return fp_operations::fetch_add(this->storage(), v, order);
722 }
723
724 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
725 {
726 return fp_operations::fetch_sub(this->storage(), v, order);
727 }
728
729 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
730 {
731 return atomics::detail::bitwise_fp_cast< value_type >(operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order));
732 }
733
734 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
735 {
736 BOOST_ASSERT(failure_order != memory_order_release);
737 BOOST_ASSERT(failure_order != memory_order_acq_rel);
738 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
739
740 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
741 }
742
743 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
744 {
745 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
746 }
747
748 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
749 {
750 BOOST_ASSERT(failure_order != memory_order_release);
751 BOOST_ASSERT(failure_order != memory_order_acq_rel);
752 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
753
754 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
755 }
756
757 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
758 {
759 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
760 }
761
762 // Boost.Atomic extensions
763 BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
764 {
765 return extra_fp_operations::fetch_negate(this->storage(), order);
766 }
767
768 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
769 {
770 return extra_fp_operations::add(this->storage(), v, order);
771 }
772
773 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
774 {
775 return extra_fp_operations::sub(this->storage(), v, order);
776 }
777
778 BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
779 {
780 return extra_fp_operations::negate(this->storage(), order);
781 }
782
783 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
784 {
785 extra_fp_operations::opaque_add(this->storage(), v, order);
786 }
787
788 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
789 {
790 extra_fp_operations::opaque_sub(this->storage(), v, order);
791 }
792
793 BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
794 {
795 extra_fp_operations::opaque_negate(this->storage(), order);
796 }
797
798 // Operators
799 BOOST_FORCEINLINE value_type operator+=(difference_type v) BOOST_NOEXCEPT
800 {
801 return add(v);
802 }
803
804 BOOST_FORCEINLINE value_type operator-=(difference_type v) BOOST_NOEXCEPT
805 {
806 return sub(v);
807 }
808
809 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
810
811 private:
812 BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::false_type) const BOOST_NOEXCEPT
813 {
814 }
815
816 BOOST_FORCEINLINE void clear_padding_bits(atomics::detail::true_type) const BOOST_NOEXCEPT
817 {
818 storage_type old_value = operations::load(this->storage(), boost::memory_order_relaxed);
819 while (true)
820 {
821 storage_type new_value = old_value;
822 atomics::detail::clear_tail_padding_bits< atomics::detail::value_sizeof< value_type >::value >(new_value);
823 bool res = operations::compare_exchange_weak(this->storage(), old_value, new_value, boost::memory_order_relaxed, boost::memory_order_relaxed);
824 if (BOOST_LIKELY(res))
825 break;
826 }
827 }
828
829 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
830 {
831 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
832 return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
833 #else
834 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
835 #endif
836 }
837
838 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
839 {
840 storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected);
841 const bool res = operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
842 expected = atomics::detail::bitwise_fp_cast< value_type >(old_value);
843 return res;
844 }
845
846 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
847 {
848 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
849 return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
850 #else
851 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
852 #endif
853 }
854
855 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
856 {
857 storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected);
858 const bool res = operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
859 expected = atomics::detail::bitwise_fp_cast< value_type >(old_value);
860 return res;
861 }
862 };
863
864 #endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
865
866
867 //! Implementation for pointers to object types
868 template< typename T >
869 class base_atomic_ref< T*, void* > :
870 public base_atomic_ref_common< T*, false >
871 {
872 private:
873 typedef base_atomic_ref_common< T*, false > base_type;
874
875 public:
876 typedef typename base_type::value_type value_type;
877 typedef std::ptrdiff_t difference_type;
878
879 protected:
880 typedef typename base_type::operations operations;
881 typedef atomics::detail::extra_operations< operations, operations::storage_size, operations::is_signed > extra_operations;
882 typedef typename base_type::storage_type storage_type;
883 typedef value_type value_arg_type;
884
885 private:
886 typedef atomics::detail::integral_constant< bool, atomics::detail::alignment_of< value_type >::value <= operations::storage_alignment > use_bitwise_cast;
887
888 // uintptr_storage_type is the minimal storage type that is enough to store pointers. The actual storage_type theoretically may be larger,
889 // if the target architecture only supports atomic ops on larger data. Typically, though, they are the same type.
890 typedef atomics::detail::uintptr_t uintptr_storage_type;
891
892 public:
893 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)) {})
894 BOOST_FORCEINLINE explicit base_atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
895 {
896 }
897
898 // Standard methods
899 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
900 {
901 BOOST_ASSERT(order != memory_order_consume);
902 BOOST_ASSERT(order != memory_order_acquire);
903 BOOST_ASSERT(order != memory_order_acq_rel);
904
905 operations::store(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order);
906 }
907
908 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const BOOST_NOEXCEPT
909 {
910 BOOST_ASSERT(order != memory_order_release);
911 BOOST_ASSERT(order != memory_order_acq_rel);
912
913 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::load(this->storage(), order)));
914 }
915
916 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
917 {
918 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::fetch_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
919 }
920
921 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
922 {
923 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::fetch_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
924 }
925
926 BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
927 {
928 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(operations::exchange(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order)));
929 }
930
931 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
932 {
933 BOOST_ASSERT(failure_order != memory_order_release);
934 BOOST_ASSERT(failure_order != memory_order_acq_rel);
935 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
936
937 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
938 }
939
940 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
941 {
942 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
943 }
944
945 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) BOOST_NOEXCEPT
946 {
947 BOOST_ASSERT(failure_order != memory_order_release);
948 BOOST_ASSERT(failure_order != memory_order_acq_rel);
949 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
950
951 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
952 }
953
954 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
955 {
956 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
957 }
958
959 // Boost.Atomic extensions
960 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
961 {
962 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(extra_operations::add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
963 }
964
965 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
966 {
967 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(extra_operations::sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order)));
968 }
969
970 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
971 {
972 extra_operations::opaque_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
973 }
974
975 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
976 {
977 extra_operations::opaque_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
978 }
979
980 BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
981 {
982 return extra_operations::add_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
983 }
984
985 BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) BOOST_NOEXCEPT
986 {
987 return extra_operations::sub_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
988 }
989
990 // Operators
991 BOOST_FORCEINLINE value_type operator++(int) BOOST_NOEXCEPT
992 {
993 return fetch_add(1);
994 }
995
996 BOOST_FORCEINLINE value_type operator++() BOOST_NOEXCEPT
997 {
998 return add(1);
999 }
1000
1001 BOOST_FORCEINLINE value_type operator--(int) BOOST_NOEXCEPT
1002 {
1003 return fetch_sub(1);
1004 }
1005
1006 BOOST_FORCEINLINE value_type operator--() BOOST_NOEXCEPT
1007 {
1008 return sub(1);
1009 }
1010
1011 BOOST_FORCEINLINE value_type operator+=(difference_type v) BOOST_NOEXCEPT
1012 {
1013 return add(v);
1014 }
1015
1016 BOOST_FORCEINLINE value_type operator-=(difference_type v) BOOST_NOEXCEPT
1017 {
1018 return sub(v);
1019 }
1020
1021 BOOST_DELETED_FUNCTION(base_atomic_ref& operator=(base_atomic_ref const&))
1022
1023 private:
1024 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
1025 {
1026 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
1027 return operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
1028 #else
1029 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
1030 #endif
1031 }
1032
1033 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
1034 {
1035 storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected);
1036 const bool res = operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
1037 expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value));
1038 return res;
1039 }
1040
1041 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
1042 {
1043 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
1044 return operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
1045 #else
1046 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
1047 #endif
1048 }
1049
1050 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
1051 {
1052 storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected);
1053 const bool res = operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
1054 expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value));
1055 return res;
1056 }
1057 };
1058
1059 } // namespace detail
1060
1061 template< typename T >
1062 class atomic_ref :
1063 public atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type >
1064 {
1065 private:
1066 typedef atomics::detail::base_atomic_ref< T, typename atomics::detail::classify< T >::type > base_type;
1067 typedef typename base_type::value_arg_type value_arg_type;
1068
1069 public:
1070 typedef typename base_type::value_type value_type;
1071
1072 BOOST_STATIC_ASSERT_MSG(sizeof(value_type) > 0u, "boost::atomic_ref<T> requires T to be a complete type");
1073 #if !defined(BOOST_ATOMIC_DETAIL_NO_CXX11_IS_TRIVIALLY_COPYABLE)
1074 BOOST_STATIC_ASSERT_MSG(atomics::detail::is_trivially_copyable< value_type >::value, "boost::atomic_ref<T> requires T to be a trivially copyable type");
1075 #endif
1076
1077 private:
1078 typedef typename base_type::storage_type storage_type;
1079
1080 public:
1081 BOOST_DEFAULTED_FUNCTION(atomic_ref(atomic_ref const& that) BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL : base_type(static_cast< base_type const& >(that)) {})
1082 BOOST_FORCEINLINE explicit atomic_ref(value_type& v) BOOST_NOEXCEPT : base_type(v)
1083 {
1084 // Check that referenced object alignment satisfies required alignment
1085 BOOST_ASSERT((((atomics::detail::uintptr_t)this->m_value) & (base_type::required_alignment - 1u)) == 0u);
1086 }
1087
1088 BOOST_FORCEINLINE value_type operator= (value_arg_type v) BOOST_NOEXCEPT
1089 {
1090 this->store(v);
1091 return v;
1092 }
1093
1094 BOOST_FORCEINLINE operator value_type() const BOOST_NOEXCEPT
1095 {
1096 return this->load();
1097 }
1098
1099 BOOST_FORCEINLINE bool is_lock_free() const BOOST_NOEXCEPT
1100 {
1101 // C++20 specifies that is_lock_free returns true if operations on *all* objects of the atomic_ref<T> type are lock-free.
1102 // This does not allow to return true or false depending on the referenced object runtime alignment. Currently, Boost.Atomic
1103 // follows this specification, although we may support runtime alignment checking in the future.
1104 return base_type::is_always_lock_free;
1105 }
1106
1107 BOOST_FORCEINLINE value_type& value() const BOOST_NOEXCEPT { return *this->m_value; }
1108
1109 BOOST_DELETED_FUNCTION(atomic_ref& operator= (atomic_ref const&))
1110 };
1111
1112 } // namespace atomics
1113 } // namespace boost
1114
1115 #if defined(BOOST_MSVC)
1116 #pragma warning(pop)
1117 #endif
1118
1119 #endif // BOOST_ATOMIC_DETAIL_ATOMIC_REF_TEMPLATE_HPP_INCLUDED_