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

source code of boost/libs/atomic/include/boost/atomic/detail/atomic_impl.hpp