]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/atomic/detail/atomic_impl.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / atomic / detail / atomic_impl.hpp
1 /*
2 * Distributed under the Boost Software License, Version 1.0.
3 * (See accompanying file LICENSE_1_0.txt or copy at
4 * http://www.boost.org/LICENSE_1_0.txt)
5 *
6 * Copyright (c) 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_trivially_default_constructible.hpp>
34 #include <boost/atomic/detail/type_traits/alignment_of.hpp>
35 #include <boost/atomic/detail/type_traits/conditional.hpp>
36 #include <boost/atomic/detail/type_traits/integral_constant.hpp>
37 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
38 #include <boost/atomic/detail/bitwise_fp_cast.hpp>
39 #include <boost/atomic/detail/fp_operations.hpp>
40 #include <boost/atomic/detail/extra_fp_operations.hpp>
41 #endif
42 #include <boost/atomic/detail/header.hpp>
43
44 #ifdef BOOST_HAS_PRAGMA_ONCE
45 #pragma once
46 #endif
47
48 /*
49 * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE,
50 * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp.
51 */
52
53 namespace boost {
54 namespace atomics {
55 namespace detail {
56
57 template< typename T, bool Signed, bool Interprocess >
58 class base_atomic_common
59 {
60 public:
61 typedef T value_type;
62
63 protected:
64 typedef atomics::detail::core_operations< storage_size_of< value_type >::value, Signed, Interprocess > core_operations;
65 typedef atomics::detail::wait_operations< core_operations > wait_operations;
66 typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type;
67 typedef typename core_operations::storage_type storage_type;
68
69 protected:
70 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;
71
72 public:
73 static BOOST_CONSTEXPR_OR_CONST bool is_always_lock_free = core_operations::is_always_lock_free;
74 static BOOST_CONSTEXPR_OR_CONST bool always_has_native_wait_notify = wait_operations::always_has_native_wait_notify;
75
76 protected:
77 BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(storage_alignment, storage_type, m_storage);
78
79 public:
80 BOOST_DEFAULTED_FUNCTION(base_atomic_common() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
81 BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic_common(storage_type v) BOOST_NOEXCEPT : m_storage(v)
82 {
83 }
84
85 BOOST_FORCEINLINE value_type& value() BOOST_NOEXCEPT { return *reinterpret_cast< value_type* >(&m_storage); }
86 BOOST_FORCEINLINE value_type volatile& value() volatile BOOST_NOEXCEPT { return *reinterpret_cast< volatile value_type* >(&m_storage); }
87 BOOST_FORCEINLINE value_type const& value() const BOOST_NOEXCEPT { return *reinterpret_cast< const value_type* >(&m_storage); }
88 BOOST_FORCEINLINE value_type const volatile& value() const volatile BOOST_NOEXCEPT { return *reinterpret_cast< const volatile value_type* >(&m_storage); }
89
90 protected:
91 BOOST_FORCEINLINE storage_type& storage() BOOST_NOEXCEPT { return m_storage; }
92 BOOST_FORCEINLINE storage_type volatile& storage() volatile BOOST_NOEXCEPT { return m_storage; }
93 BOOST_FORCEINLINE storage_type const& storage() const BOOST_NOEXCEPT { return m_storage; }
94 BOOST_FORCEINLINE storage_type const volatile& storage() const volatile BOOST_NOEXCEPT { return m_storage; }
95
96 public:
97 BOOST_FORCEINLINE bool is_lock_free() const volatile BOOST_NOEXCEPT
98 {
99 // C++17 requires all instances of atomic<> return a value consistent with is_always_lock_free here.
100 // Boost.Atomic also enforces the required alignment of the atomic storage, so we can always return is_always_lock_free.
101 return is_always_lock_free;
102 }
103
104 BOOST_FORCEINLINE bool has_native_wait_notify() const volatile BOOST_NOEXCEPT
105 {
106 return wait_operations::has_native_wait_notify(this->storage());
107 }
108
109 BOOST_FORCEINLINE void notify_one() volatile BOOST_NOEXCEPT
110 {
111 wait_operations::notify_one(this->storage());
112 }
113
114 BOOST_FORCEINLINE void notify_all() volatile BOOST_NOEXCEPT
115 {
116 wait_operations::notify_all(this->storage());
117 }
118 };
119
120 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
121 template< typename T, bool Signed, bool Interprocess >
122 BOOST_CONSTEXPR_OR_CONST bool base_atomic_common< T, Signed, Interprocess >::is_always_lock_free;
123 template< typename T, bool Signed, bool Interprocess >
124 BOOST_CONSTEXPR_OR_CONST bool base_atomic_common< T, Signed, Interprocess >::always_has_native_wait_notify;
125 #endif
126
127
128 template< typename T, bool Interprocess, bool IsTriviallyDefaultConstructible = atomics::detail::is_trivially_default_constructible< T >::value >
129 class base_atomic_generic;
130
131 template< typename T, bool Interprocess >
132 class base_atomic_generic< T, Interprocess, true > :
133 public base_atomic_common< T, false, Interprocess >
134 {
135 private:
136 typedef base_atomic_common< T, false, Interprocess > base_type;
137
138 protected:
139 typedef typename base_type::storage_type storage_type;
140 typedef typename base_type::value_arg_type value_arg_type;
141
142 public:
143 BOOST_DEFAULTED_FUNCTION(base_atomic_generic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
144 BOOST_FORCEINLINE explicit base_atomic_generic(value_arg_type v) BOOST_NOEXCEPT : base_type(atomics::detail::bitwise_cast< storage_type >(v))
145 {
146 }
147 };
148
149 template< typename T, bool Interprocess >
150 class base_atomic_generic< T, Interprocess, false > :
151 public base_atomic_common< T, false, Interprocess >
152 {
153 private:
154 typedef base_atomic_common< T, false, Interprocess > base_type;
155
156 public:
157 typedef typename base_type::value_type value_type;
158
159 protected:
160 typedef typename base_type::storage_type storage_type;
161 typedef typename base_type::value_arg_type value_arg_type;
162
163 public:
164 BOOST_FORCEINLINE explicit base_atomic_generic(value_arg_type v = value_type()) BOOST_NOEXCEPT : base_type(atomics::detail::bitwise_cast< storage_type >(v))
165 {
166 }
167 };
168
169
170 template< typename T, typename Kind, bool Interprocess >
171 class base_atomic;
172
173 //! General template. Implementation for user-defined types, such as structs and enums, and pointers to non-object types
174 template< typename T, bool Interprocess >
175 class base_atomic< T, void, Interprocess > :
176 public base_atomic_generic< T, Interprocess >
177 {
178 private:
179 typedef base_atomic_generic< T, Interprocess > base_type;
180
181 public:
182 typedef typename base_type::value_type value_type;
183
184 protected:
185 typedef typename base_type::core_operations core_operations;
186 typedef typename base_type::wait_operations wait_operations;
187 typedef typename base_type::storage_type storage_type;
188 typedef typename base_type::value_arg_type value_arg_type;
189
190 private:
191 typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast;
192
193 public:
194 BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
195 BOOST_FORCEINLINE explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(v)
196 {
197 }
198
199 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
200 {
201 BOOST_ASSERT(order != memory_order_consume);
202 BOOST_ASSERT(order != memory_order_acquire);
203 BOOST_ASSERT(order != memory_order_acq_rel);
204
205 core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order);
206 }
207
208 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
209 {
210 BOOST_ASSERT(order != memory_order_release);
211 BOOST_ASSERT(order != memory_order_acq_rel);
212
213 return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order));
214 }
215
216 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
217 {
218 return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order));
219 }
220
221 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
222 {
223 BOOST_ASSERT(failure_order != memory_order_release);
224 BOOST_ASSERT(failure_order != memory_order_acq_rel);
225 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
226
227 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
228 }
229
230 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
231 {
232 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
233 }
234
235 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
236 {
237 BOOST_ASSERT(failure_order != memory_order_release);
238 BOOST_ASSERT(failure_order != memory_order_acq_rel);
239 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
240
241 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
242 }
243
244 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
245 {
246 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
247 }
248
249 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
250 {
251 BOOST_ASSERT(order != memory_order_release);
252 BOOST_ASSERT(order != memory_order_acq_rel);
253
254 return atomics::detail::bitwise_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_cast< storage_type >(old_val), order));
255 }
256
257 BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
258 BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
259
260 private:
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::false_type) volatile BOOST_NOEXCEPT
262 {
263 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
264 return core_operations::compare_exchange_strong(this->storage(), 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::true_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::true_type) volatile BOOST_NOEXCEPT
271 {
272 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
273 const bool res = core_operations::compare_exchange_strong(this->storage(), 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::false_type) volatile BOOST_NOEXCEPT
279 {
280 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
281 return core_operations::compare_exchange_weak(this->storage(), 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::true_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::true_type) volatile BOOST_NOEXCEPT
288 {
289 storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected);
290 const bool res = core_operations::compare_exchange_weak(this->storage(), 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
298 template< typename T, bool Interprocess >
299 class base_atomic< T, int, Interprocess > :
300 public base_atomic_common< T, atomics::detail::is_signed< T >::value, Interprocess >
301 {
302 private:
303 typedef base_atomic_common< T, atomics::detail::is_signed< T >::value, Interprocess > base_type;
304
305 public:
306 typedef typename base_type::value_type value_type;
307 typedef value_type difference_type;
308
309 protected:
310 typedef typename base_type::core_operations core_operations;
311 typedef typename base_type::wait_operations wait_operations;
312 typedef atomics::detail::extra_operations< core_operations > extra_operations;
313 typedef typename base_type::storage_type storage_type;
314 typedef value_type value_arg_type;
315
316 private:
317 typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast;
318
319 public:
320 BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
321 BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(static_cast< storage_type >(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 core_operations::store(this->storage(), static_cast< 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 >(core_operations::load(this->storage(), 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 >(core_operations::fetch_add(this->storage(), static_cast< 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 >(core_operations::fetch_sub(this->storage(), static_cast< 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 >(core_operations::exchange(this->storage(), static_cast< 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, use_bitwise_cast());
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, use_bitwise_cast());
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 >(core_operations::fetch_and(this->storage(), static_cast< 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 >(core_operations::fetch_or(this->storage(), static_cast< 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 >(core_operations::fetch_xor(this->storage(), static_cast< 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(this->storage(), 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(this->storage(), 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(this->storage(), static_cast< 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(this->storage(), static_cast< 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(this->storage(), 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(this->storage(), static_cast< 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(this->storage(), static_cast< 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(this->storage(), static_cast< 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(this->storage(), 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(this->storage(), static_cast< 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(this->storage(), static_cast< 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(this->storage(), 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(this->storage(), static_cast< 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(this->storage(), static_cast< 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(this->storage(), static_cast< 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(this->storage(), order);
478 }
479
480 BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
481 {
482 return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order);
483 }
484
485 BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
486 {
487 return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order);
488 }
489
490 BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
491 {
492 return extra_operations::negate_and_test(this->storage(), order);
493 }
494
495 BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
496 {
497 return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order);
498 }
499
500 BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
501 {
502 return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order);
503 }
504
505 BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
506 {
507 return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order);
508 }
509
510 BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
511 {
512 return extra_operations::complement_and_test(this->storage(), order);
513 }
514
515 BOOST_FORCEINLINE bool bit_test_and_set(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
516 {
517 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
518 return extra_operations::bit_test_and_set(this->storage(), bit_number, order);
519 }
520
521 BOOST_FORCEINLINE bool bit_test_and_reset(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
522 {
523 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
524 return extra_operations::bit_test_and_reset(this->storage(), bit_number, order);
525 }
526
527 BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
528 {
529 BOOST_ASSERT(bit_number < sizeof(value_type) * 8u);
530 return extra_operations::bit_test_and_complement(this->storage(), bit_number, order);
531 }
532
533 // Operators
534 BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
535 {
536 return fetch_add(1);
537 }
538
539 BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT
540 {
541 return add(1);
542 }
543
544 BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT
545 {
546 return fetch_sub(1);
547 }
548
549 BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT
550 {
551 return sub(1);
552 }
553
554 BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
555 {
556 return add(v);
557 }
558
559 BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
560 {
561 return sub(v);
562 }
563
564 BOOST_FORCEINLINE value_type operator&=(value_type v) volatile BOOST_NOEXCEPT
565 {
566 return bitwise_and(v);
567 }
568
569 BOOST_FORCEINLINE value_type operator|=(value_type v) volatile BOOST_NOEXCEPT
570 {
571 return bitwise_or(v);
572 }
573
574 BOOST_FORCEINLINE value_type operator^=(value_type v) volatile BOOST_NOEXCEPT
575 {
576 return bitwise_xor(v);
577 }
578
579 BOOST_FORCEINLINE value_type wait(value_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
580 {
581 BOOST_ASSERT(order != memory_order_release);
582 BOOST_ASSERT(order != memory_order_acq_rel);
583
584 return atomics::detail::integral_truncate< value_type >(wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order));
585 }
586
587 BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
588 BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
589
590 private:
591 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
592 {
593 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
594 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
595 #else
596 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
597 #endif
598 }
599
600 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
601 {
602 storage_type old_value = static_cast< storage_type >(expected);
603 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
604 expected = atomics::detail::integral_truncate< value_type >(old_value);
605 return res;
606 }
607
608 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
609 {
610 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
611 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
612 #else
613 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
614 #endif
615 }
616
617 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
618 {
619 storage_type old_value = static_cast< storage_type >(expected);
620 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
621 expected = atomics::detail::integral_truncate< value_type >(old_value);
622 return res;
623 }
624 };
625
626 //! Implementation for bool
627 template< bool Interprocess >
628 class base_atomic< bool, int, Interprocess > :
629 public base_atomic_common< bool, false, Interprocess >
630 {
631 private:
632 typedef base_atomic_common< bool, false, Interprocess > base_type;
633
634 public:
635 typedef typename base_type::value_type value_type;
636
637 protected:
638 typedef typename base_type::core_operations core_operations;
639 typedef typename base_type::wait_operations wait_operations;
640 typedef typename base_type::storage_type storage_type;
641 typedef value_type value_arg_type;
642
643 private:
644 typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast;
645
646 public:
647 BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
648 BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(static_cast< storage_type >(v)) {}
649
650 // Standard methods
651 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
652 {
653 BOOST_ASSERT(order != memory_order_consume);
654 BOOST_ASSERT(order != memory_order_acquire);
655 BOOST_ASSERT(order != memory_order_acq_rel);
656
657 core_operations::store(this->storage(), static_cast< storage_type >(v), order);
658 }
659
660 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
661 {
662 BOOST_ASSERT(order != memory_order_release);
663 BOOST_ASSERT(order != memory_order_acq_rel);
664
665 return !!core_operations::load(this->storage(), order);
666 }
667
668 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
669 {
670 return !!core_operations::exchange(this->storage(), static_cast< storage_type >(v), order);
671 }
672
673 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
674 {
675 BOOST_ASSERT(failure_order != memory_order_release);
676 BOOST_ASSERT(failure_order != memory_order_acq_rel);
677 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
678
679 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
680 }
681
682 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
683 {
684 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
685 }
686
687 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
688 {
689 BOOST_ASSERT(failure_order != memory_order_release);
690 BOOST_ASSERT(failure_order != memory_order_acq_rel);
691 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
692
693 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
694 }
695
696 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
697 {
698 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
699 }
700
701 BOOST_FORCEINLINE value_type wait(value_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
702 {
703 BOOST_ASSERT(order != memory_order_release);
704 BOOST_ASSERT(order != memory_order_acq_rel);
705
706 return !!wait_operations::wait(this->storage(), static_cast< storage_type >(old_val), order);
707 }
708
709 BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
710 BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
711
712 private:
713 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
714 {
715 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
716 return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
717 #else
718 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
719 #endif
720 }
721
722 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
723 {
724 storage_type old_value = static_cast< storage_type >(expected);
725 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
726 expected = !!old_value;
727 return res;
728 }
729
730 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
731 {
732 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
733 return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order);
734 #else
735 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
736 #endif
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::true_type) volatile BOOST_NOEXCEPT
740 {
741 storage_type old_value = static_cast< storage_type >(expected);
742 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order);
743 expected = !!old_value;
744 return res;
745 }
746 };
747
748
749 #if !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
750
751 //! Implementation for floating point types
752 template< typename T, bool Interprocess >
753 class base_atomic< T, float, Interprocess > :
754 public base_atomic_common< T, false, Interprocess >
755 {
756 private:
757 typedef base_atomic_common< T, false, Interprocess > base_type;
758
759 public:
760 typedef typename base_type::value_type value_type;
761 typedef value_type difference_type;
762
763 protected:
764 typedef typename base_type::core_operations core_operations;
765 typedef typename base_type::wait_operations wait_operations;
766 typedef atomics::detail::extra_operations< core_operations > extra_operations;
767 typedef atomics::detail::fp_operations< extra_operations, value_type > fp_operations;
768 typedef atomics::detail::extra_fp_operations< fp_operations > extra_fp_operations;
769 typedef typename base_type::storage_type storage_type;
770 typedef value_type value_arg_type;
771
772 private:
773 typedef atomics::detail::integral_constant< bool,
774 atomics::detail::value_sizeof< value_type >::value != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment
775 > use_bitwise_cast;
776
777 public:
778 BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
779 BOOST_FORCEINLINE explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(atomics::detail::bitwise_fp_cast< storage_type >(v)) {}
780
781 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
782 {
783 BOOST_ASSERT(order != memory_order_consume);
784 BOOST_ASSERT(order != memory_order_acquire);
785 BOOST_ASSERT(order != memory_order_acq_rel);
786
787 core_operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order);
788 }
789
790 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
791 {
792 BOOST_ASSERT(order != memory_order_release);
793 BOOST_ASSERT(order != memory_order_acq_rel);
794
795 return atomics::detail::bitwise_fp_cast< value_type >(core_operations::load(this->storage(), order));
796 }
797
798 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
799 {
800 return fp_operations::fetch_add(this->storage(), v, order);
801 }
802
803 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
804 {
805 return fp_operations::fetch_sub(this->storage(), v, order);
806 }
807
808 BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
809 {
810 return atomics::detail::bitwise_fp_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order));
811 }
812
813 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
814 {
815 BOOST_ASSERT(failure_order != memory_order_release);
816 BOOST_ASSERT(failure_order != memory_order_acq_rel);
817 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
818
819 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
820 }
821
822 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
823 {
824 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
825 }
826
827 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
828 {
829 BOOST_ASSERT(failure_order != memory_order_release);
830 BOOST_ASSERT(failure_order != memory_order_acq_rel);
831 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
832
833 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
834 }
835
836 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
837 {
838 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
839 }
840
841 // Boost.Atomic extensions
842 BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
843 {
844 return extra_fp_operations::fetch_negate(this->storage(), order);
845 }
846
847 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
848 {
849 return extra_fp_operations::add(this->storage(), v, order);
850 }
851
852 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
853 {
854 return extra_fp_operations::sub(this->storage(), v, order);
855 }
856
857 BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
858 {
859 return extra_fp_operations::negate(this->storage(), order);
860 }
861
862 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
863 {
864 extra_fp_operations::opaque_add(this->storage(), v, order);
865 }
866
867 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
868 {
869 extra_fp_operations::opaque_sub(this->storage(), v, order);
870 }
871
872 BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
873 {
874 extra_fp_operations::opaque_negate(this->storage(), order);
875 }
876
877 // Operators
878 BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
879 {
880 return add(v);
881 }
882
883 BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
884 {
885 return sub(v);
886 }
887
888 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
889 {
890 BOOST_ASSERT(order != memory_order_release);
891 BOOST_ASSERT(order != memory_order_acq_rel);
892
893 return atomics::detail::bitwise_fp_cast< value_type >(wait_operations::wait(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(old_val), order));
894 }
895
896 BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
897 BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
898
899 private:
900 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
901 {
902 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
903 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);
904 #else
905 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
906 #endif
907 }
908
909 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
910 {
911 storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected);
912 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
913 expected = atomics::detail::bitwise_fp_cast< value_type >(old_value);
914 return res;
915 }
916
917 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
918 {
919 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
920 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);
921 #else
922 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
923 #endif
924 }
925
926 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
927 {
928 storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected);
929 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_fp_cast< storage_type >(desired), success_order, failure_order);
930 expected = atomics::detail::bitwise_fp_cast< value_type >(old_value);
931 return res;
932 }
933 };
934
935 #endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT)
936
937
938 //! Implementation for pointers to object types
939 template< typename T, bool Interprocess >
940 class base_atomic< T*, void*, Interprocess > :
941 public base_atomic_common< T*, false, Interprocess >
942 {
943 private:
944 typedef base_atomic_common< T*, false, Interprocess > base_type;
945
946 public:
947 typedef typename base_type::value_type value_type;
948 typedef std::ptrdiff_t difference_type;
949
950 protected:
951 typedef typename base_type::core_operations core_operations;
952 typedef typename base_type::wait_operations wait_operations;
953 typedef atomics::detail::extra_operations< core_operations > extra_operations;
954 typedef typename base_type::storage_type storage_type;
955 typedef value_type value_arg_type;
956
957 private:
958 typedef atomics::detail::integral_constant< bool, sizeof(value_type) != sizeof(storage_type) || atomics::detail::alignment_of< value_type >::value <= core_operations::storage_alignment > use_bitwise_cast;
959
960 // uintptr_storage_type is the minimal storage type that is enough to store pointers. The actual storage_type theoretically may be larger,
961 // if the target architecture only supports atomic ops on larger data. Typically, though, they are the same type.
962 typedef atomics::detail::uintptr_t uintptr_storage_type;
963
964 public:
965 BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {})
966 BOOST_FORCEINLINE explicit base_atomic(value_arg_type v) BOOST_NOEXCEPT : base_type(atomics::detail::bitwise_cast< uintptr_storage_type >(v))
967 {
968 }
969
970 // Standard methods
971 BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
972 {
973 BOOST_ASSERT(order != memory_order_consume);
974 BOOST_ASSERT(order != memory_order_acquire);
975 BOOST_ASSERT(order != memory_order_acq_rel);
976
977 core_operations::store(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order);
978 }
979
980 BOOST_FORCEINLINE value_type load(memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
981 {
982 BOOST_ASSERT(order != memory_order_release);
983 BOOST_ASSERT(order != memory_order_acq_rel);
984
985 return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(core_operations::load(this->storage(), order)));
986 }
987
988 BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
989 {
990 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)));
991 }
992
993 BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
994 {
995 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)));
996 }
997
998 BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
999 {
1000 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)));
1001 }
1002
1003 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
1004 {
1005 BOOST_ASSERT(failure_order != memory_order_release);
1006 BOOST_ASSERT(failure_order != memory_order_acq_rel);
1007 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
1008
1009 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
1010 }
1011
1012 BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1013 {
1014 return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order));
1015 }
1016
1017 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order success_order, memory_order failure_order) volatile BOOST_NOEXCEPT
1018 {
1019 BOOST_ASSERT(failure_order != memory_order_release);
1020 BOOST_ASSERT(failure_order != memory_order_acq_rel);
1021 BOOST_ASSERT(cas_failure_order_must_not_be_stronger_than_success_order(success_order, failure_order));
1022
1023 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, use_bitwise_cast());
1024 }
1025
1026 BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1027 {
1028 return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order));
1029 }
1030
1031 // Boost.Atomic extensions
1032 BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1033 {
1034 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)));
1035 }
1036
1037 BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1038 {
1039 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)));
1040 }
1041
1042 BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1043 {
1044 extra_operations::opaque_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
1045 }
1046
1047 BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1048 {
1049 extra_operations::opaque_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
1050 }
1051
1052 BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1053 {
1054 return extra_operations::add_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
1055 }
1056
1057 BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT
1058 {
1059 return extra_operations::sub_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order);
1060 }
1061
1062 // Operators
1063 BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT
1064 {
1065 return fetch_add(1);
1066 }
1067
1068 BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT
1069 {
1070 return add(1);
1071 }
1072
1073 BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT
1074 {
1075 return fetch_sub(1);
1076 }
1077
1078 BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT
1079 {
1080 return sub(1);
1081 }
1082
1083 BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT
1084 {
1085 return add(v);
1086 }
1087
1088 BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT
1089 {
1090 return sub(v);
1091 }
1092
1093 BOOST_FORCEINLINE value_type wait(value_arg_type old_val, memory_order order = memory_order_seq_cst) const volatile BOOST_NOEXCEPT
1094 {
1095 BOOST_ASSERT(order != memory_order_release);
1096 BOOST_ASSERT(order != memory_order_acq_rel);
1097
1098 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)));
1099 }
1100
1101 BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&))
1102 BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&))
1103
1104 private:
1105 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
1106 {
1107 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
1108 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);
1109 #else
1110 return compare_exchange_strong_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
1111 #endif
1112 }
1113
1114 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
1115 {
1116 storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected);
1117 const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
1118 expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value));
1119 return res;
1120 }
1121
1122 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
1123 {
1124 #if defined(BOOST_ATOMIC_DETAIL_STORAGE_TYPE_MAY_ALIAS)
1125 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);
1126 #else
1127 return compare_exchange_weak_impl(expected, desired, success_order, failure_order, atomics::detail::true_type());
1128 #endif
1129 }
1130
1131 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
1132 {
1133 storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected);
1134 const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< uintptr_storage_type >(desired), success_order, failure_order);
1135 expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value));
1136 return res;
1137 }
1138 };
1139
1140 } // namespace detail
1141 } // namespace atomics
1142 } // namespace boost
1143
1144 #include <boost/atomic/detail/footer.hpp>
1145
1146 #endif // BOOST_ATOMIC_DETAIL_ATOMIC_IMPl_HPP_INCLUDED_