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