]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/atomic/detail/extra_ops_generic.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / atomic / detail / extra_ops_generic.hpp
CommitLineData
b32b8144
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) 2015 Andrey Semashev
7 */
8/*!
9 * \file atomic/detail/extra_ops_generic.hpp
10 *
11 * This header contains generic implementation of the extra atomic operations.
12 */
13
14#ifndef BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_
15#define BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_
16
17#include <cstddef>
18#include <boost/memory_order.hpp>
19#include <boost/atomic/detail/config.hpp>
f67539c2
TL
20#include <boost/atomic/detail/storage_traits.hpp>
21#include <boost/atomic/detail/integral_conversions.hpp>
b32b8144 22#include <boost/atomic/detail/extra_operations_fwd.hpp>
20effc67 23#include <boost/atomic/detail/header.hpp>
b32b8144
FG
24
25#ifdef BOOST_HAS_PRAGMA_ONCE
26#pragma once
27#endif
28
b32b8144
FG
29namespace boost {
30namespace atomics {
31namespace detail {
32
33//! Generic implementation of extra operations
11fdf7f2 34template< typename Base, std::size_t Size, bool Signed, bool = Base::full_cas_based >
20effc67 35struct extra_operations_generic :
b32b8144
FG
36 public Base
37{
38 typedef Base base_type;
39 typedef typename base_type::storage_type storage_type;
f67539c2 40 typedef typename storage_traits< Size >::type emulated_storage_type;
b32b8144
FG
41
42 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
43 {
44 storage_type old_val;
45 atomics::detail::non_atomic_load(storage, old_val);
11fdf7f2 46 while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {}
b32b8144
FG
47 return old_val;
48 }
49
11fdf7f2
TL
50 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
51 {
52 storage_type old_val, new_val;
53 atomics::detail::non_atomic_load(storage, old_val);
54 do
55 {
56 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val));
57 }
58 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
59 return new_val;
60 }
61
62 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
63 {
64 return base_type::fetch_add(storage, v, order) + v;
65 }
66
67 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
68 {
69 return base_type::fetch_sub(storage, v, order) - v;
70 }
71
72 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
73 {
74 return base_type::fetch_and(storage, v, order) & v;
75 }
76
77 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
78 {
79 return base_type::fetch_or(storage, v, order) | v;
80 }
81
82 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
83 {
84 return base_type::fetch_xor(storage, v, order) ^ v;
85 }
86
b32b8144
FG
87 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
88 {
11fdf7f2
TL
89 return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
90 }
91
92 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
93 {
94 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u)));
95 return base_type::fetch_xor(storage, mask, order) ^ mask;
b32b8144
FG
96 }
97
98 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
99 {
11fdf7f2 100 base_type::fetch_add(storage, v, order);
b32b8144
FG
101 }
102
103 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
104 {
11fdf7f2 105 base_type::fetch_sub(storage, v, order);
b32b8144
FG
106 }
107
108 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
109 {
110 fetch_negate(storage, order);
111 }
112
113 static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
114 {
11fdf7f2 115 base_type::fetch_and(storage, v, order);
b32b8144
FG
116 }
117
118 static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
119 {
11fdf7f2 120 base_type::fetch_or(storage, v, order);
b32b8144
FG
121 }
122
123 static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
124 {
11fdf7f2 125 base_type::fetch_xor(storage, v, order);
b32b8144
FG
126 }
127
128 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
129 {
130 fetch_complement(storage, order);
131 }
132
133 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
134 {
11fdf7f2 135 return !!static_cast< emulated_storage_type >(add(storage, v, order));
b32b8144
FG
136 }
137
138 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
139 {
11fdf7f2
TL
140 return !!static_cast< emulated_storage_type >(sub(storage, v, order));
141 }
142
143 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
144 {
145 return !!negate(storage, order);
b32b8144
FG
146 }
147
148 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
149 {
11fdf7f2 150 return !!bitwise_and(storage, v, order);
b32b8144
FG
151 }
152
153 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
154 {
11fdf7f2 155 return !!bitwise_or(storage, v, order);
b32b8144
FG
156 }
157
158 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
159 {
11fdf7f2
TL
160 return !!bitwise_xor(storage, v, order);
161 }
162
163 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
164 {
165 return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order));
166 }
167
168 static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
169 {
170 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
171 storage_type old_val = base_type::fetch_or(storage, mask, order);
172 return !!(old_val & mask);
173 }
174
175 static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
176 {
177 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
178 storage_type old_val = base_type::fetch_and(storage, ~mask, order);
179 return !!(old_val & mask);
180 }
181
182 static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
183 {
184 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
185 storage_type old_val = base_type::fetch_xor(storage, mask, order);
186 return !!(old_val & mask);
187 }
188};
189
190//! Specialization for cases when the platform only natively supports CAS
191template< typename Base, std::size_t Size, bool Signed >
20effc67 192struct extra_operations_generic< Base, Size, Signed, true > :
11fdf7f2
TL
193 public Base
194{
195 typedef Base base_type;
196 typedef typename base_type::storage_type storage_type;
f67539c2 197 typedef typename storage_traits< Size >::type emulated_storage_type;
11fdf7f2
TL
198
199 static BOOST_FORCEINLINE storage_type fetch_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
200 {
201 storage_type old_val;
202 atomics::detail::non_atomic_load(storage, old_val);
203 while (!base_type::compare_exchange_weak(storage, old_val, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val)), order, memory_order_relaxed)) {}
204 return old_val;
205 }
206
207 static BOOST_FORCEINLINE storage_type negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
208 {
209 storage_type old_val, new_val;
210 atomics::detail::non_atomic_load(storage, old_val);
211 do
212 {
213 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(-old_val));
214 }
215 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
216 return new_val;
217 }
218
219 static BOOST_FORCEINLINE storage_type add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
220 {
221 storage_type old_val, new_val;
222 atomics::detail::non_atomic_load(storage, old_val);
223 do
224 {
225 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val + v));
226 }
227 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
228 return new_val;
229 }
230
231 static BOOST_FORCEINLINE storage_type sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
232 {
233 storage_type old_val, new_val;
234 atomics::detail::non_atomic_load(storage, old_val);
235 do
236 {
237 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val - v));
238 }
239 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
240 return new_val;
241 }
242
243 static BOOST_FORCEINLINE storage_type bitwise_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
244 {
245 storage_type old_val, new_val;
246 atomics::detail::non_atomic_load(storage, old_val);
247 do
248 {
249 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val & v));
250 }
251 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
252 return new_val;
253 }
254
255 static BOOST_FORCEINLINE storage_type bitwise_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
256 {
257 storage_type old_val, new_val;
258 atomics::detail::non_atomic_load(storage, old_val);
259 do
260 {
261 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val | v));
262 }
263 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
264 return new_val;
265 }
266
267 static BOOST_FORCEINLINE storage_type bitwise_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
268 {
269 storage_type old_val, new_val;
270 atomics::detail::non_atomic_load(storage, old_val);
271 do
272 {
273 new_val = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(old_val ^ v));
274 }
275 while (!base_type::compare_exchange_weak(storage, old_val, new_val, order, memory_order_relaxed));
276 return new_val;
277 }
278
279 static BOOST_FORCEINLINE storage_type fetch_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
280 {
281 return base_type::fetch_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
282 }
283
284 static BOOST_FORCEINLINE storage_type bitwise_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
285 {
286 return bitwise_xor(storage, atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(~static_cast< emulated_storage_type >(0u))), order);
287 }
288
289 static BOOST_FORCEINLINE void opaque_add(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
290 {
291 base_type::fetch_add(storage, v, order);
292 }
293
294 static BOOST_FORCEINLINE void opaque_sub(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
295 {
296 base_type::fetch_sub(storage, v, order);
297 }
298
299 static BOOST_FORCEINLINE void opaque_negate(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
300 {
301 fetch_negate(storage, order);
302 }
303
304 static BOOST_FORCEINLINE void opaque_and(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
305 {
306 base_type::fetch_and(storage, v, order);
307 }
308
309 static BOOST_FORCEINLINE void opaque_or(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
310 {
311 base_type::fetch_or(storage, v, order);
312 }
313
314 static BOOST_FORCEINLINE void opaque_xor(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
315 {
316 base_type::fetch_xor(storage, v, order);
317 }
318
319 static BOOST_FORCEINLINE void opaque_complement(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
320 {
321 fetch_complement(storage, order);
322 }
323
324 static BOOST_FORCEINLINE bool add_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
325 {
326 return !!static_cast< emulated_storage_type >(add(storage, v, order));
327 }
328
329 static BOOST_FORCEINLINE bool sub_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
330 {
331 return !!static_cast< emulated_storage_type >(sub(storage, v, order));
332 }
333
334 static BOOST_FORCEINLINE bool negate_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
335 {
336 return !!negate(storage, order);
337 }
338
339 static BOOST_FORCEINLINE bool and_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
340 {
341 return !!bitwise_and(storage, v, order);
342 }
343
344 static BOOST_FORCEINLINE bool or_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
345 {
346 return !!bitwise_or(storage, v, order);
347 }
348
349 static BOOST_FORCEINLINE bool xor_and_test(storage_type volatile& storage, storage_type v, memory_order order) BOOST_NOEXCEPT
350 {
351 return !!bitwise_xor(storage, v, order);
352 }
353
354 static BOOST_FORCEINLINE bool complement_and_test(storage_type volatile& storage, memory_order order) BOOST_NOEXCEPT
355 {
356 return !!static_cast< emulated_storage_type >(bitwise_complement(storage, order));
b32b8144
FG
357 }
358
359 static BOOST_FORCEINLINE bool bit_test_and_set(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
360 {
11fdf7f2
TL
361 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
362 storage_type old_val = base_type::fetch_or(storage, mask, order);
b32b8144
FG
363 return !!(old_val & mask);
364 }
365
366 static BOOST_FORCEINLINE bool bit_test_and_reset(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
367 {
11fdf7f2
TL
368 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
369 storage_type old_val = base_type::fetch_and(storage, ~mask, order);
b32b8144
FG
370 return !!(old_val & mask);
371 }
372
373 static BOOST_FORCEINLINE bool bit_test_and_complement(storage_type volatile& storage, unsigned int bit_number, memory_order order) BOOST_NOEXCEPT
374 {
11fdf7f2
TL
375 const storage_type mask = atomics::detail::integral_extend< Signed, storage_type >(static_cast< emulated_storage_type >(static_cast< emulated_storage_type >(1u) << bit_number));
376 storage_type old_val = base_type::fetch_xor(storage, mask, order);
b32b8144
FG
377 return !!(old_val & mask);
378 }
379};
380
381// Default extra_operations template definition will be used unless specialized for a specific platform
382template< typename Base, std::size_t Size, bool Signed >
11fdf7f2 383struct extra_operations< Base, Size, Signed, true > :
20effc67 384 public extra_operations_generic< Base, Size, Signed >
b32b8144
FG
385{
386};
387
388} // namespace detail
389} // namespace atomics
390} // namespace boost
391
20effc67 392#include <boost/atomic/detail/footer.hpp>
b32b8144
FG
393
394#endif // BOOST_ATOMIC_DETAIL_EXTRA_OPS_GENERIC_HPP_INCLUDED_