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