]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | |
f67539c2 | 8 | * Copyright (c) 2014-2020 Andrey Semashev |
7c673cae FG |
9 | */ |
10 | /*! | |
20effc67 | 11 | * \file atomic/detail/atomic_impl.hpp |
7c673cae | 12 | * |
20effc67 | 13 | * This header contains implementation of \c atomic template. |
7c673cae FG |
14 | */ |
15 | ||
20effc67 TL |
16 | #ifndef BOOST_ATOMIC_DETAIL_ATOMIC_IMPL_HPP_INCLUDED_ |
17 | #define BOOST_ATOMIC_DETAIL_ATOMIC_IMPL_HPP_INCLUDED_ | |
7c673cae FG |
18 | |
19 | #include <cstddef> | |
7c673cae | 20 | #include <boost/assert.hpp> |
f67539c2 | 21 | #include <boost/memory_order.hpp> |
7c673cae | 22 | #include <boost/atomic/detail/config.hpp> |
f67539c2 | 23 | #include <boost/atomic/detail/intptr.hpp> |
f67539c2 | 24 | #include <boost/atomic/detail/storage_traits.hpp> |
7c673cae | 25 | #include <boost/atomic/detail/bitwise_cast.hpp> |
f67539c2 | 26 | #include <boost/atomic/detail/integral_conversions.hpp> |
20effc67 TL |
27 | #include <boost/atomic/detail/core_operations.hpp> |
28 | #include <boost/atomic/detail/wait_operations.hpp> | |
f67539c2 TL |
29 | #include <boost/atomic/detail/extra_operations.hpp> |
30 | #include <boost/atomic/detail/memory_order_utils.hpp> | |
20effc67 | 31 | #include <boost/atomic/detail/aligned_variable.hpp> |
b32b8144 | 32 | #include <boost/atomic/detail/type_traits/is_signed.hpp> |
1e59de90 | 33 | #include <boost/atomic/detail/type_traits/is_nothrow_default_constructible.hpp> |
11fdf7f2 | 34 | #include <boost/atomic/detail/type_traits/is_trivially_default_constructible.hpp> |
f67539c2 | 35 | #include <boost/atomic/detail/type_traits/alignment_of.hpp> |
b32b8144 | 36 | #include <boost/atomic/detail/type_traits/conditional.hpp> |
11fdf7f2 TL |
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> | |
f67539c2 TL |
40 | #include <boost/atomic/detail/fp_operations.hpp> |
41 | #include <boost/atomic/detail/extra_fp_operations.hpp> | |
42 | #endif | |
20effc67 | 43 | #include <boost/atomic/detail/header.hpp> |
7c673cae FG |
44 | |
45 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
46 | #pragma once | |
47 | #endif | |
48 | ||
1e59de90 TL |
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 | ||
7c673cae FG |
55 | /* |
56 | * IMPLEMENTATION NOTE: All interface functions MUST be declared with BOOST_FORCEINLINE, | |
20effc67 | 57 | * see comment for convert_memory_order_to_gcc in gcc_atomic_memory_order_utils.hpp. |
7c673cae FG |
58 | */ |
59 | ||
60 | namespace boost { | |
61 | namespace atomics { | |
62 | namespace detail { | |
63 | ||
20effc67 | 64 | template< typename T, bool Signed, bool Interprocess > |
f67539c2 | 65 | class base_atomic_common |
b32b8144 | 66 | { |
f67539c2 TL |
67 | public: |
68 | typedef T value_type; | |
b32b8144 | 69 | |
f67539c2 | 70 | protected: |
20effc67 TL |
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; | |
f67539c2 | 73 | typedef typename atomics::detail::conditional< sizeof(value_type) <= sizeof(void*), value_type, value_type const& >::type value_arg_type; |
20effc67 | 74 | typedef typename core_operations::storage_type storage_type; |
7c673cae | 75 | |
f67539c2 | 76 | protected: |
20effc67 TL |
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; | |
11fdf7f2 | 82 | |
f67539c2 | 83 | protected: |
20effc67 | 84 | BOOST_ATOMIC_DETAIL_ALIGNED_VAR_TPL(storage_alignment, storage_type, m_storage); |
7c673cae | 85 | |
f67539c2 | 86 | public: |
1e59de90 TL |
87 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT base_atomic_common() BOOST_NOEXCEPT : m_storage() |
88 | { | |
89 | } | |
90 | ||
f67539c2 TL |
91 | BOOST_FORCEINLINE BOOST_ATOMIC_DETAIL_CONSTEXPR_UNION_INIT explicit base_atomic_common(storage_type v) BOOST_NOEXCEPT : m_storage(v) |
92 | { | |
93 | } | |
b32b8144 | 94 | |
f67539c2 TL |
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); } | |
b32b8144 | 99 | |
f67539c2 TL |
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; } | |
20effc67 TL |
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 | } | |
f67539c2 | 128 | }; |
b32b8144 | 129 | |
20effc67 TL |
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 | ||
7c673cae | 137 | |
20effc67 | 138 | template< typename T, bool Interprocess, bool IsTriviallyDefaultConstructible = atomics::detail::is_trivially_default_constructible< T >::value > |
11fdf7f2 | 139 | class base_atomic_generic; |
7c673cae | 140 | |
20effc67 TL |
141 | template< typename T, bool Interprocess > |
142 | class base_atomic_generic< T, Interprocess, true > : | |
143 | public base_atomic_common< T, false, Interprocess > | |
b32b8144 | 144 | { |
f67539c2 | 145 | private: |
20effc67 | 146 | typedef base_atomic_common< T, false, Interprocess > base_type; |
b32b8144 | 147 | |
11fdf7f2 | 148 | protected: |
f67539c2 TL |
149 | typedef typename base_type::storage_type storage_type; |
150 | typedef typename base_type::value_arg_type value_arg_type; | |
11fdf7f2 TL |
151 | |
152 | public: | |
153 | BOOST_DEFAULTED_FUNCTION(base_atomic_generic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) | |
1e59de90 TL |
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)) | |
11fdf7f2 TL |
156 | { |
157 | } | |
158 | }; | |
159 | ||
20effc67 TL |
160 | template< typename T, bool Interprocess > |
161 | class base_atomic_generic< T, Interprocess, false > : | |
162 | public base_atomic_common< T, false, Interprocess > | |
11fdf7f2 | 163 | { |
f67539c2 | 164 | private: |
20effc67 | 165 | typedef base_atomic_common< T, false, Interprocess > base_type; |
11fdf7f2 TL |
166 | |
167 | public: | |
f67539c2 | 168 | typedef typename base_type::value_type value_type; |
b32b8144 FG |
169 | |
170 | protected: | |
f67539c2 TL |
171 | typedef typename base_type::storage_type storage_type; |
172 | typedef typename base_type::value_arg_type value_arg_type; | |
b32b8144 FG |
173 | |
174 | public: | |
1e59de90 TL |
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)) | |
11fdf7f2 TL |
177 | { |
178 | } | |
179 | }; | |
180 | ||
181 | ||
20effc67 | 182 | template< typename T, typename Kind, bool Interprocess > |
11fdf7f2 TL |
183 | class base_atomic; |
184 | ||
1e59de90 | 185 | //! General template. Implementation for user-defined types, such as structs, and pointers to non-object types |
20effc67 TL |
186 | template< typename T, bool Interprocess > |
187 | class base_atomic< T, void, Interprocess > : | |
188 | public base_atomic_generic< T, Interprocess > | |
11fdf7f2 TL |
189 | { |
190 | private: | |
20effc67 | 191 | typedef base_atomic_generic< T, Interprocess > base_type; |
11fdf7f2 TL |
192 | |
193 | public: | |
194 | typedef typename base_type::value_type value_type; | |
11fdf7f2 TL |
195 | |
196 | protected: | |
20effc67 TL |
197 | typedef typename base_type::core_operations core_operations; |
198 | typedef typename base_type::wait_operations wait_operations; | |
f67539c2 | 199 | typedef typename base_type::storage_type storage_type; |
11fdf7f2 TL |
200 | typedef typename base_type::value_arg_type value_arg_type; |
201 | ||
202 | private: | |
1e59de90 TL |
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 | |
11fdf7f2 TL |
208 | |
209 | public: | |
1e59de90 TL |
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) | |
b32b8144 FG |
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 | ||
20effc67 | 224 | core_operations::store(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order); |
b32b8144 FG |
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 | ||
20effc67 | 232 | return atomics::detail::bitwise_cast< value_type >(core_operations::load(this->storage(), order)); |
b32b8144 FG |
233 | } |
234 | ||
235 | BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
236 | { | |
20effc67 | 237 | return atomics::detail::bitwise_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_cast< storage_type >(v), order)); |
b32b8144 FG |
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 | ||
1e59de90 | 246 | return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
b32b8144 FG |
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 | ||
1e59de90 | 260 | return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
b32b8144 FG |
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 | ||
20effc67 TL |
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 | ||
b32b8144 FG |
276 | BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) |
277 | BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) | |
278 | ||
279 | private: | |
f67539c2 | 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 |
b32b8144 | 281 | { |
20effc67 | 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); |
b32b8144 FG |
283 | } |
284 | ||
f67539c2 | 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 |
b32b8144 FG |
286 | { |
287 | storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); | |
20effc67 | 288 | const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); |
b32b8144 FG |
289 | expected = atomics::detail::bitwise_cast< value_type >(old_value); |
290 | return res; | |
291 | } | |
292 | ||
f67539c2 | 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 |
b32b8144 | 294 | { |
20effc67 | 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); |
b32b8144 FG |
296 | } |
297 | ||
f67539c2 | 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 |
b32b8144 FG |
299 | { |
300 | storage_type old_value = atomics::detail::bitwise_cast< storage_type >(expected); | |
20effc67 | 301 | const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, atomics::detail::bitwise_cast< storage_type >(desired), success_order, failure_order); |
b32b8144 FG |
302 | expected = atomics::detail::bitwise_cast< value_type >(old_value); |
303 | return res; | |
304 | } | |
305 | }; | |
306 | ||
307 | ||
1e59de90 TL |
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 | ||
7c673cae | 428 | //! Implementation for integers |
20effc67 TL |
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 > | |
7c673cae | 432 | { |
f67539c2 | 433 | private: |
20effc67 | 434 | typedef base_atomic_common< T, atomics::detail::is_signed< T >::value, Interprocess > base_type; |
f67539c2 | 435 | |
b32b8144 | 436 | public: |
f67539c2 TL |
437 | typedef typename base_type::value_type value_type; |
438 | typedef value_type difference_type; | |
7c673cae FG |
439 | |
440 | protected: | |
20effc67 TL |
441 | typedef typename base_type::core_operations core_operations; |
442 | typedef typename base_type::wait_operations wait_operations; | |
443 | typedef atomics::detail::extra_operations< core_operations > extra_operations; | |
f67539c2 | 444 | typedef typename base_type::storage_type storage_type; |
7c673cae FG |
445 | typedef value_type value_arg_type; |
446 | ||
11fdf7f2 | 447 | private: |
1e59de90 TL |
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 | |
7c673cae FG |
453 | |
454 | public: | |
11fdf7f2 | 455 | BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) |
f67539c2 | 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)) {} |
7c673cae | 457 | |
b32b8144 | 458 | // Standard methods |
11fdf7f2 | 459 | BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
460 | { |
461 | BOOST_ASSERT(order != memory_order_consume); | |
462 | BOOST_ASSERT(order != memory_order_acquire); | |
463 | BOOST_ASSERT(order != memory_order_acq_rel); | |
464 | ||
20effc67 | 465 | core_operations::store(this->storage(), static_cast< storage_type >(v), order); |
7c673cae FG |
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 | ||
20effc67 | 473 | return atomics::detail::integral_truncate< value_type >(core_operations::load(this->storage(), order)); |
7c673cae FG |
474 | } |
475 | ||
476 | BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
477 | { | |
20effc67 | 478 | return atomics::detail::integral_truncate< value_type >(core_operations::fetch_add(this->storage(), static_cast< storage_type >(v), order)); |
7c673cae FG |
479 | } |
480 | ||
481 | BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
482 | { | |
20effc67 | 483 | return atomics::detail::integral_truncate< value_type >(core_operations::fetch_sub(this->storage(), static_cast< storage_type >(v), order)); |
7c673cae FG |
484 | } |
485 | ||
11fdf7f2 | 486 | BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 487 | { |
20effc67 | 488 | return atomics::detail::integral_truncate< value_type >(core_operations::exchange(this->storage(), static_cast< storage_type >(v), order)); |
7c673cae FG |
489 | } |
490 | ||
11fdf7f2 | 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 |
7c673cae FG |
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 | ||
1e59de90 | 497 | return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
7c673cae FG |
498 | } |
499 | ||
11fdf7f2 | 500 | BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
501 | { |
502 | return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); | |
503 | } | |
504 | ||
11fdf7f2 | 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 |
7c673cae FG |
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 | ||
1e59de90 | 511 | return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
7c673cae FG |
512 | } |
513 | ||
11fdf7f2 | 514 | BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
515 | { |
516 | return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); | |
517 | } | |
518 | ||
11fdf7f2 | 519 | BOOST_FORCEINLINE value_type fetch_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 520 | { |
20effc67 | 521 | return atomics::detail::integral_truncate< value_type >(core_operations::fetch_and(this->storage(), static_cast< storage_type >(v), order)); |
7c673cae FG |
522 | } |
523 | ||
11fdf7f2 | 524 | BOOST_FORCEINLINE value_type fetch_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 525 | { |
20effc67 | 526 | return atomics::detail::integral_truncate< value_type >(core_operations::fetch_or(this->storage(), static_cast< storage_type >(v), order)); |
7c673cae FG |
527 | } |
528 | ||
11fdf7f2 | 529 | BOOST_FORCEINLINE value_type fetch_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 530 | { |
20effc67 | 531 | return atomics::detail::integral_truncate< value_type >(core_operations::fetch_xor(this->storage(), static_cast< storage_type >(v), order)); |
7c673cae FG |
532 | } |
533 | ||
b32b8144 FG |
534 | // Boost.Atomic extensions |
535 | BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
536 | { | |
f67539c2 | 537 | return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_negate(this->storage(), order)); |
b32b8144 FG |
538 | } |
539 | ||
540 | BOOST_FORCEINLINE value_type fetch_complement(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
541 | { | |
f67539c2 | 542 | return atomics::detail::integral_truncate< value_type >(extra_operations::fetch_complement(this->storage(), order)); |
11fdf7f2 TL |
543 | } |
544 | ||
545 | BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
546 | { | |
f67539c2 | 547 | return atomics::detail::integral_truncate< value_type >(extra_operations::add(this->storage(), static_cast< storage_type >(v), order)); |
11fdf7f2 TL |
548 | } |
549 | ||
550 | BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
551 | { | |
f67539c2 | 552 | return atomics::detail::integral_truncate< value_type >(extra_operations::sub(this->storage(), static_cast< storage_type >(v), order)); |
11fdf7f2 TL |
553 | } |
554 | ||
555 | BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
556 | { | |
f67539c2 | 557 | return atomics::detail::integral_truncate< value_type >(extra_operations::negate(this->storage(), order)); |
11fdf7f2 TL |
558 | } |
559 | ||
560 | BOOST_FORCEINLINE value_type bitwise_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
561 | { | |
f67539c2 | 562 | return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_and(this->storage(), static_cast< storage_type >(v), order)); |
11fdf7f2 TL |
563 | } |
564 | ||
565 | BOOST_FORCEINLINE value_type bitwise_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
566 | { | |
f67539c2 | 567 | return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_or(this->storage(), static_cast< storage_type >(v), order)); |
11fdf7f2 TL |
568 | } |
569 | ||
570 | BOOST_FORCEINLINE value_type bitwise_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
571 | { | |
f67539c2 | 572 | return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_xor(this->storage(), static_cast< storage_type >(v), order)); |
11fdf7f2 TL |
573 | } |
574 | ||
575 | BOOST_FORCEINLINE value_type bitwise_complement(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
576 | { | |
f67539c2 | 577 | return atomics::detail::integral_truncate< value_type >(extra_operations::bitwise_complement(this->storage(), order)); |
b32b8144 FG |
578 | } |
579 | ||
580 | BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
581 | { | |
f67539c2 | 582 | extra_operations::opaque_add(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
583 | } |
584 | ||
585 | BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
586 | { | |
f67539c2 | 587 | extra_operations::opaque_sub(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
588 | } |
589 | ||
590 | BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
591 | { | |
f67539c2 | 592 | extra_operations::opaque_negate(this->storage(), order); |
b32b8144 FG |
593 | } |
594 | ||
11fdf7f2 | 595 | BOOST_FORCEINLINE void opaque_and(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
b32b8144 | 596 | { |
f67539c2 | 597 | extra_operations::opaque_and(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
598 | } |
599 | ||
11fdf7f2 | 600 | BOOST_FORCEINLINE void opaque_or(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
b32b8144 | 601 | { |
f67539c2 | 602 | extra_operations::opaque_or(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
603 | } |
604 | ||
11fdf7f2 | 605 | BOOST_FORCEINLINE void opaque_xor(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
b32b8144 | 606 | { |
f67539c2 | 607 | extra_operations::opaque_xor(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
608 | } |
609 | ||
610 | BOOST_FORCEINLINE void opaque_complement(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
611 | { | |
f67539c2 | 612 | extra_operations::opaque_complement(this->storage(), order); |
b32b8144 FG |
613 | } |
614 | ||
615 | BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
616 | { | |
f67539c2 | 617 | return extra_operations::add_and_test(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
618 | } |
619 | ||
620 | BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
621 | { | |
f67539c2 | 622 | return extra_operations::sub_and_test(this->storage(), static_cast< storage_type >(v), order); |
11fdf7f2 TL |
623 | } |
624 | ||
625 | BOOST_FORCEINLINE bool negate_and_test(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
626 | { | |
f67539c2 | 627 | return extra_operations::negate_and_test(this->storage(), order); |
b32b8144 FG |
628 | } |
629 | ||
11fdf7f2 | 630 | BOOST_FORCEINLINE bool and_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
b32b8144 | 631 | { |
f67539c2 | 632 | return extra_operations::and_and_test(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
633 | } |
634 | ||
11fdf7f2 | 635 | BOOST_FORCEINLINE bool or_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
b32b8144 | 636 | { |
f67539c2 | 637 | return extra_operations::or_and_test(this->storage(), static_cast< storage_type >(v), order); |
b32b8144 FG |
638 | } |
639 | ||
11fdf7f2 | 640 | BOOST_FORCEINLINE bool xor_and_test(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
b32b8144 | 641 | { |
f67539c2 | 642 | return extra_operations::xor_and_test(this->storage(), static_cast< storage_type >(v), order); |
11fdf7f2 TL |
643 | } |
644 | ||
645 | BOOST_FORCEINLINE bool complement_and_test(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
646 | { | |
f67539c2 | 647 | return extra_operations::complement_and_test(this->storage(), order); |
b32b8144 FG |
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); | |
f67539c2 | 653 | return extra_operations::bit_test_and_set(this->storage(), bit_number, order); |
b32b8144 FG |
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); | |
f67539c2 | 659 | return extra_operations::bit_test_and_reset(this->storage(), bit_number, order); |
b32b8144 FG |
660 | } |
661 | ||
662 | BOOST_FORCEINLINE bool bit_test_and_complement(unsigned int bit_number, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
7c673cae | 663 | { |
b32b8144 | 664 | BOOST_ASSERT(bit_number < sizeof(value_type) * 8u); |
f67539c2 | 665 | return extra_operations::bit_test_and_complement(this->storage(), bit_number, order); |
7c673cae FG |
666 | } |
667 | ||
b32b8144 | 668 | // Operators |
7c673cae FG |
669 | BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT |
670 | { | |
671 | return fetch_add(1); | |
672 | } | |
673 | ||
674 | BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT | |
675 | { | |
11fdf7f2 | 676 | return add(1); |
7c673cae FG |
677 | } |
678 | ||
679 | BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT | |
680 | { | |
681 | return fetch_sub(1); | |
682 | } | |
683 | ||
684 | BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT | |
685 | { | |
11fdf7f2 | 686 | return sub(1); |
7c673cae FG |
687 | } |
688 | ||
689 | BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT | |
690 | { | |
11fdf7f2 | 691 | return add(v); |
7c673cae FG |
692 | } |
693 | ||
694 | BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT | |
695 | { | |
11fdf7f2 | 696 | return sub(v); |
7c673cae FG |
697 | } |
698 | ||
699 | BOOST_FORCEINLINE value_type operator&=(value_type v) volatile BOOST_NOEXCEPT | |
700 | { | |
11fdf7f2 | 701 | return bitwise_and(v); |
7c673cae FG |
702 | } |
703 | ||
704 | BOOST_FORCEINLINE value_type operator|=(value_type v) volatile BOOST_NOEXCEPT | |
705 | { | |
11fdf7f2 | 706 | return bitwise_or(v); |
7c673cae FG |
707 | } |
708 | ||
709 | BOOST_FORCEINLINE value_type operator^=(value_type v) volatile BOOST_NOEXCEPT | |
710 | { | |
11fdf7f2 | 711 | return bitwise_xor(v); |
7c673cae FG |
712 | } |
713 | ||
20effc67 TL |
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 | ||
7c673cae FG |
722 | BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) |
723 | BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) | |
11fdf7f2 TL |
724 | |
725 | private: | |
f67539c2 | 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 |
11fdf7f2 | 727 | { |
20effc67 | 728 | return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); |
11fdf7f2 TL |
729 | } |
730 | ||
f67539c2 | 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 |
11fdf7f2 | 732 | { |
f67539c2 | 733 | storage_type old_value = static_cast< storage_type >(expected); |
20effc67 | 734 | const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); |
11fdf7f2 TL |
735 | expected = atomics::detail::integral_truncate< value_type >(old_value); |
736 | return res; | |
737 | } | |
738 | ||
f67539c2 | 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 |
11fdf7f2 | 740 | { |
20effc67 | 741 | return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); |
11fdf7f2 TL |
742 | } |
743 | ||
f67539c2 | 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 |
11fdf7f2 | 745 | { |
f67539c2 | 746 | storage_type old_value = static_cast< storage_type >(expected); |
20effc67 | 747 | const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); |
11fdf7f2 TL |
748 | expected = atomics::detail::integral_truncate< value_type >(old_value); |
749 | return res; | |
750 | } | |
7c673cae FG |
751 | }; |
752 | ||
753 | //! Implementation for bool | |
20effc67 TL |
754 | template< bool Interprocess > |
755 | class base_atomic< bool, int, Interprocess > : | |
756 | public base_atomic_common< bool, false, Interprocess > | |
7c673cae | 757 | { |
f67539c2 | 758 | private: |
20effc67 | 759 | typedef base_atomic_common< bool, false, Interprocess > base_type; |
f67539c2 | 760 | |
b32b8144 | 761 | public: |
20effc67 | 762 | typedef typename base_type::value_type value_type; |
7c673cae FG |
763 | |
764 | protected: | |
20effc67 TL |
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; | |
7c673cae FG |
768 | typedef value_type value_arg_type; |
769 | ||
11fdf7f2 | 770 | private: |
1e59de90 TL |
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 | |
7c673cae FG |
776 | |
777 | public: | |
11fdf7f2 | 778 | BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) |
f67539c2 | 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)) {} |
7c673cae | 780 | |
b32b8144 | 781 | // Standard methods |
11fdf7f2 | 782 | BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
783 | { |
784 | BOOST_ASSERT(order != memory_order_consume); | |
785 | BOOST_ASSERT(order != memory_order_acquire); | |
786 | BOOST_ASSERT(order != memory_order_acq_rel); | |
787 | ||
20effc67 | 788 | core_operations::store(this->storage(), static_cast< storage_type >(v), order); |
7c673cae FG |
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 | ||
20effc67 | 796 | return !!core_operations::load(this->storage(), order); |
7c673cae FG |
797 | } |
798 | ||
11fdf7f2 | 799 | BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 800 | { |
20effc67 | 801 | return !!core_operations::exchange(this->storage(), static_cast< storage_type >(v), order); |
7c673cae FG |
802 | } |
803 | ||
11fdf7f2 | 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 |
7c673cae FG |
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 | ||
1e59de90 | 810 | return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
11fdf7f2 TL |
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 | ||
1e59de90 | 824 | return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
11fdf7f2 TL |
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 | ||
20effc67 TL |
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 | ||
11fdf7f2 TL |
840 | BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) |
841 | BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) | |
842 | ||
843 | private: | |
f67539c2 | 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 |
11fdf7f2 | 845 | { |
20effc67 | 846 | return core_operations::compare_exchange_strong(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); |
11fdf7f2 TL |
847 | } |
848 | ||
f67539c2 | 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 |
11fdf7f2 | 850 | { |
7c673cae | 851 | storage_type old_value = static_cast< storage_type >(expected); |
20effc67 | 852 | const bool res = core_operations::compare_exchange_strong(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); |
7c673cae FG |
853 | expected = !!old_value; |
854 | return res; | |
11fdf7f2 TL |
855 | } |
856 | ||
f67539c2 | 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 |
11fdf7f2 | 858 | { |
20effc67 | 859 | return core_operations::compare_exchange_weak(this->storage(), reinterpret_cast< storage_type& >(expected), static_cast< storage_type >(desired), success_order, failure_order); |
7c673cae FG |
860 | } |
861 | ||
f67539c2 | 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 |
11fdf7f2 TL |
863 | { |
864 | storage_type old_value = static_cast< storage_type >(expected); | |
20effc67 | 865 | const bool res = core_operations::compare_exchange_weak(this->storage(), old_value, static_cast< storage_type >(desired), success_order, failure_order); |
11fdf7f2 TL |
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 | |
20effc67 TL |
875 | template< typename T, bool Interprocess > |
876 | class base_atomic< T, float, Interprocess > : | |
877 | public base_atomic_common< T, false, Interprocess > | |
11fdf7f2 | 878 | { |
f67539c2 | 879 | private: |
20effc67 | 880 | typedef base_atomic_common< T, false, Interprocess > base_type; |
f67539c2 | 881 | |
11fdf7f2 | 882 | public: |
f67539c2 TL |
883 | typedef typename base_type::value_type value_type; |
884 | typedef value_type difference_type; | |
11fdf7f2 TL |
885 | |
886 | protected: | |
20effc67 TL |
887 | typedef typename base_type::core_operations core_operations; |
888 | typedef typename base_type::wait_operations wait_operations; | |
889 | typedef atomics::detail::extra_operations< core_operations > extra_operations; | |
890 | typedef atomics::detail::fp_operations< extra_operations, value_type > fp_operations; | |
891 | typedef atomics::detail::extra_fp_operations< fp_operations > extra_fp_operations; | |
f67539c2 | 892 | typedef typename base_type::storage_type storage_type; |
11fdf7f2 TL |
893 | typedef value_type value_arg_type; |
894 | ||
11fdf7f2 | 895 | private: |
1e59de90 TL |
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 | |
f67539c2 | 899 | typedef atomics::detail::integral_constant< bool, |
1e59de90 TL |
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 | |
11fdf7f2 TL |
903 | |
904 | public: | |
905 | BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) | |
1e59de90 TL |
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 | } | |
11fdf7f2 TL |
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 | ||
20effc67 | 917 | core_operations::store(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order); |
11fdf7f2 TL |
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 | ||
20effc67 | 925 | return atomics::detail::bitwise_fp_cast< value_type >(core_operations::load(this->storage(), order)); |
11fdf7f2 TL |
926 | } |
927 | ||
928 | BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
929 | { | |
f67539c2 | 930 | return fp_operations::fetch_add(this->storage(), v, order); |
11fdf7f2 TL |
931 | } |
932 | ||
933 | BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
934 | { | |
f67539c2 | 935 | return fp_operations::fetch_sub(this->storage(), v, order); |
11fdf7f2 TL |
936 | } |
937 | ||
938 | BOOST_FORCEINLINE value_type exchange(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
939 | { | |
20effc67 | 940 | return atomics::detail::bitwise_fp_cast< value_type >(core_operations::exchange(this->storage(), atomics::detail::bitwise_fp_cast< storage_type >(v), order)); |
11fdf7f2 TL |
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 | ||
1e59de90 | 949 | return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
11fdf7f2 TL |
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 | |
7c673cae FG |
953 | { |
954 | return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); | |
955 | } | |
956 | ||
11fdf7f2 | 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 |
7c673cae FG |
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 | ||
1e59de90 | 963 | return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
7c673cae FG |
964 | } |
965 | ||
11fdf7f2 | 966 | BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
967 | { |
968 | return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); | |
969 | } | |
970 | ||
11fdf7f2 TL |
971 | // Boost.Atomic extensions |
972 | BOOST_FORCEINLINE value_type fetch_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
973 | { | |
f67539c2 | 974 | return extra_fp_operations::fetch_negate(this->storage(), order); |
11fdf7f2 TL |
975 | } |
976 | ||
977 | BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
978 | { | |
f67539c2 | 979 | return extra_fp_operations::add(this->storage(), v, order); |
11fdf7f2 TL |
980 | } |
981 | ||
982 | BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
983 | { | |
f67539c2 | 984 | return extra_fp_operations::sub(this->storage(), v, order); |
11fdf7f2 TL |
985 | } |
986 | ||
987 | BOOST_FORCEINLINE value_type negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
988 | { | |
f67539c2 | 989 | return extra_fp_operations::negate(this->storage(), order); |
11fdf7f2 TL |
990 | } |
991 | ||
992 | BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
993 | { | |
f67539c2 | 994 | extra_fp_operations::opaque_add(this->storage(), v, order); |
11fdf7f2 TL |
995 | } |
996 | ||
997 | BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
998 | { | |
f67539c2 | 999 | extra_fp_operations::opaque_sub(this->storage(), v, order); |
11fdf7f2 TL |
1000 | } |
1001 | ||
1002 | BOOST_FORCEINLINE void opaque_negate(memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
1003 | { | |
f67539c2 | 1004 | extra_fp_operations::opaque_negate(this->storage(), order); |
11fdf7f2 TL |
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 | ||
20effc67 TL |
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 | ||
7c673cae FG |
1026 | BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) |
1027 | BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) | |
11fdf7f2 TL |
1028 | |
1029 | private: | |
f67539c2 | 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 |
11fdf7f2 | 1031 | { |
20effc67 | 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); |
11fdf7f2 TL |
1033 | } |
1034 | ||
f67539c2 | 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 |
11fdf7f2 TL |
1036 | { |
1037 | storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); | |
20effc67 | 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); |
11fdf7f2 TL |
1039 | expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); |
1040 | return res; | |
1041 | } | |
1042 | ||
f67539c2 | 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 |
11fdf7f2 | 1044 | { |
20effc67 | 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); |
11fdf7f2 TL |
1046 | } |
1047 | ||
f67539c2 | 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 |
11fdf7f2 TL |
1049 | { |
1050 | storage_type old_value = atomics::detail::bitwise_fp_cast< storage_type >(expected); | |
20effc67 | 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); |
11fdf7f2 TL |
1052 | expected = atomics::detail::bitwise_fp_cast< value_type >(old_value); |
1053 | return res; | |
1054 | } | |
7c673cae FG |
1055 | }; |
1056 | ||
11fdf7f2 TL |
1057 | #endif // !defined(BOOST_ATOMIC_NO_FLOATING_POINT) |
1058 | ||
7c673cae | 1059 | |
b32b8144 | 1060 | //! Implementation for pointers to object types |
20effc67 TL |
1061 | template< typename T, bool Interprocess > |
1062 | class base_atomic< T*, void*, Interprocess > : | |
1063 | public base_atomic_common< T*, false, Interprocess > | |
7c673cae | 1064 | { |
f67539c2 | 1065 | private: |
20effc67 | 1066 | typedef base_atomic_common< T*, false, Interprocess > base_type; |
f67539c2 | 1067 | |
b32b8144 | 1068 | public: |
f67539c2 | 1069 | typedef typename base_type::value_type value_type; |
7c673cae FG |
1070 | typedef std::ptrdiff_t difference_type; |
1071 | ||
1072 | protected: | |
20effc67 TL |
1073 | typedef typename base_type::core_operations core_operations; |
1074 | typedef typename base_type::wait_operations wait_operations; | |
1075 | typedef atomics::detail::extra_operations< core_operations > extra_operations; | |
f67539c2 | 1076 | typedef typename base_type::storage_type storage_type; |
7c673cae FG |
1077 | typedef value_type value_arg_type; |
1078 | ||
11fdf7f2 | 1079 | private: |
1e59de90 TL |
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 | |
11fdf7f2 TL |
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. | |
f67539c2 | 1088 | typedef atomics::detail::uintptr_t uintptr_storage_type; |
7c673cae FG |
1089 | |
1090 | public: | |
11fdf7f2 | 1091 | BOOST_DEFAULTED_FUNCTION(base_atomic() BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_DECL, BOOST_ATOMIC_DETAIL_DEF_NOEXCEPT_IMPL {}) |
1e59de90 TL |
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)) | |
7c673cae FG |
1094 | { |
1095 | } | |
1096 | ||
b32b8144 | 1097 | // Standard methods |
11fdf7f2 | 1098 | BOOST_FORCEINLINE void store(value_arg_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
1099 | { |
1100 | BOOST_ASSERT(order != memory_order_consume); | |
1101 | BOOST_ASSERT(order != memory_order_acquire); | |
1102 | BOOST_ASSERT(order != memory_order_acq_rel); | |
1103 | ||
20effc67 | 1104 | core_operations::store(this->storage(), atomics::detail::bitwise_cast< uintptr_storage_type >(v), order); |
7c673cae FG |
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 | ||
20effc67 | 1112 | return atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(core_operations::load(this->storage(), order))); |
7c673cae FG |
1113 | } |
1114 | ||
1115 | BOOST_FORCEINLINE value_type fetch_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
1116 | { | |
20effc67 | 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))); |
7c673cae FG |
1118 | } |
1119 | ||
1120 | BOOST_FORCEINLINE value_type fetch_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
1121 | { | |
20effc67 | 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))); |
7c673cae FG |
1123 | } |
1124 | ||
1125 | BOOST_FORCEINLINE value_type exchange(value_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
1126 | { | |
20effc67 | 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))); |
7c673cae FG |
1128 | } |
1129 | ||
11fdf7f2 | 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 |
7c673cae FG |
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 | ||
1e59de90 | 1136 | return compare_exchange_strong_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
7c673cae FG |
1137 | } |
1138 | ||
11fdf7f2 | 1139 | BOOST_FORCEINLINE bool compare_exchange_strong(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
1140 | { |
1141 | return compare_exchange_strong(expected, desired, order, atomics::detail::deduce_failure_order(order)); | |
1142 | } | |
1143 | ||
11fdf7f2 | 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 |
7c673cae FG |
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 | ||
1e59de90 | 1150 | return compare_exchange_weak_impl(expected, desired, success_order, failure_order, cxchg_use_bitwise_cast()); |
7c673cae FG |
1151 | } |
1152 | ||
11fdf7f2 | 1153 | BOOST_FORCEINLINE bool compare_exchange_weak(value_type& expected, value_arg_type desired, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae FG |
1154 | { |
1155 | return compare_exchange_weak(expected, desired, order, atomics::detail::deduce_failure_order(order)); | |
1156 | } | |
1157 | ||
b32b8144 | 1158 | // Boost.Atomic extensions |
11fdf7f2 TL |
1159 | BOOST_FORCEINLINE value_type add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
1160 | { | |
f67539c2 | 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))); |
11fdf7f2 TL |
1162 | } |
1163 | ||
1164 | BOOST_FORCEINLINE value_type sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT | |
1165 | { | |
f67539c2 | 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))); |
11fdf7f2 TL |
1167 | } |
1168 | ||
b32b8144 | 1169 | BOOST_FORCEINLINE void opaque_add(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 1170 | { |
f67539c2 | 1171 | extra_operations::opaque_add(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); |
7c673cae FG |
1172 | } |
1173 | ||
b32b8144 | 1174 | BOOST_FORCEINLINE void opaque_sub(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 1175 | { |
f67539c2 | 1176 | extra_operations::opaque_sub(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); |
7c673cae FG |
1177 | } |
1178 | ||
b32b8144 | 1179 | BOOST_FORCEINLINE bool add_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 1180 | { |
f67539c2 | 1181 | return extra_operations::add_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); |
7c673cae FG |
1182 | } |
1183 | ||
b32b8144 | 1184 | BOOST_FORCEINLINE bool sub_and_test(difference_type v, memory_order order = memory_order_seq_cst) volatile BOOST_NOEXCEPT |
7c673cae | 1185 | { |
f67539c2 | 1186 | return extra_operations::sub_and_test(this->storage(), static_cast< uintptr_storage_type >(v * sizeof(T)), order); |
7c673cae FG |
1187 | } |
1188 | ||
b32b8144 | 1189 | // Operators |
7c673cae FG |
1190 | BOOST_FORCEINLINE value_type operator++(int) volatile BOOST_NOEXCEPT |
1191 | { | |
1192 | return fetch_add(1); | |
1193 | } | |
1194 | ||
1195 | BOOST_FORCEINLINE value_type operator++() volatile BOOST_NOEXCEPT | |
1196 | { | |
11fdf7f2 | 1197 | return add(1); |
7c673cae FG |
1198 | } |
1199 | ||
1200 | BOOST_FORCEINLINE value_type operator--(int) volatile BOOST_NOEXCEPT | |
1201 | { | |
1202 | return fetch_sub(1); | |
1203 | } | |
1204 | ||
1205 | BOOST_FORCEINLINE value_type operator--() volatile BOOST_NOEXCEPT | |
1206 | { | |
11fdf7f2 | 1207 | return sub(1); |
7c673cae FG |
1208 | } |
1209 | ||
1210 | BOOST_FORCEINLINE value_type operator+=(difference_type v) volatile BOOST_NOEXCEPT | |
1211 | { | |
11fdf7f2 | 1212 | return add(v); |
7c673cae FG |
1213 | } |
1214 | ||
1215 | BOOST_FORCEINLINE value_type operator-=(difference_type v) volatile BOOST_NOEXCEPT | |
1216 | { | |
11fdf7f2 | 1217 | return sub(v); |
7c673cae FG |
1218 | } |
1219 | ||
20effc67 TL |
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 | ||
7c673cae FG |
1228 | BOOST_DELETED_FUNCTION(base_atomic(base_atomic const&)) |
1229 | BOOST_DELETED_FUNCTION(base_atomic& operator=(base_atomic const&)) | |
11fdf7f2 TL |
1230 | |
1231 | private: | |
f67539c2 | 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 |
11fdf7f2 | 1233 | { |
20effc67 | 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); |
11fdf7f2 TL |
1235 | } |
1236 | ||
f67539c2 | 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 |
11fdf7f2 TL |
1238 | { |
1239 | storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected); | |
20effc67 | 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); |
11fdf7f2 TL |
1241 | expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value)); |
1242 | return res; | |
1243 | } | |
1244 | ||
f67539c2 | 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 |
11fdf7f2 | 1246 | { |
20effc67 | 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); |
11fdf7f2 TL |
1248 | } |
1249 | ||
f67539c2 | 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 |
11fdf7f2 TL |
1251 | { |
1252 | storage_type old_value = atomics::detail::bitwise_cast< uintptr_storage_type >(expected); | |
20effc67 | 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); |
11fdf7f2 TL |
1254 | expected = atomics::detail::bitwise_cast< value_type >(static_cast< uintptr_storage_type >(old_value)); |
1255 | return res; | |
1256 | } | |
7c673cae FG |
1257 | }; |
1258 | ||
1259 | } // namespace detail | |
7c673cae FG |
1260 | } // namespace atomics |
1261 | } // namespace boost | |
1262 | ||
20effc67 | 1263 | #include <boost/atomic/detail/footer.hpp> |
7c673cae | 1264 | |
20effc67 | 1265 | #endif // BOOST_ATOMIC_DETAIL_ATOMIC_IMPl_HPP_INCLUDED_ |