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