1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef _LIBCPP___ATOMIC_ATOMIC_H
10#define _LIBCPP___ATOMIC_ATOMIC_H
11
12#include <__atomic/atomic_base.h>
13#include <__atomic/check_memory_order.h>
14#include <__atomic/cxx_atomic_impl.h>
15#include <__atomic/memory_order.h>
16#include <__config>
17#include <__functional/operations.h>
18#include <__memory/addressof.h>
19#include <__type_traits/is_floating_point.h>
20#include <__type_traits/is_function.h>
21#include <__type_traits/is_same.h>
22#include <__type_traits/remove_const.h>
23#include <__type_traits/remove_pointer.h>
24#include <__type_traits/remove_volatile.h>
25#include <__utility/forward.h>
26#include <cstddef>
27#include <cstring>
28
29#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30# pragma GCC system_header
31#endif
32
33_LIBCPP_BEGIN_NAMESPACE_STD
34
35template <class _Tp>
36struct atomic : public __atomic_base<_Tp> {
37 using __base = __atomic_base<_Tp>;
38 using value_type = _Tp;
39 using difference_type = value_type;
40
41#if _LIBCPP_STD_VER >= 20
42 _LIBCPP_HIDE_FROM_ABI atomic() = default;
43#else
44 _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
45#endif
46
47 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
48
49 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile _NOEXCEPT {
50 __base::store(__d);
51 return __d;
52 }
53 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) _NOEXCEPT {
54 __base::store(__d);
55 return __d;
56 }
57
58 atomic& operator=(const atomic&) = delete;
59 atomic& operator=(const atomic&) volatile = delete;
60};
61
62// atomic<T*>
63
64template <class _Tp>
65struct atomic<_Tp*> : public __atomic_base<_Tp*> {
66 using __base = __atomic_base<_Tp*>;
67 using value_type = _Tp*;
68 using difference_type = ptrdiff_t;
69
70 _LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
71
72 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
73
74 _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) volatile _NOEXCEPT {
75 __base::store(__d);
76 return __d;
77 }
78 _LIBCPP_HIDE_FROM_ABI _Tp* operator=(_Tp* __d) _NOEXCEPT {
79 __base::store(__d);
80 return __d;
81 }
82
83 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
84 // __atomic_fetch_add accepts function pointers, guard against them.
85 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
86 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
87 }
88
89 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
90 // __atomic_fetch_add accepts function pointers, guard against them.
91 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
92 return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
93 }
94
95 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
96 // __atomic_fetch_add accepts function pointers, guard against them.
97 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
98 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
99 }
100
101 _LIBCPP_HIDE_FROM_ABI _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
102 // __atomic_fetch_add accepts function pointers, guard against them.
103 static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
104 return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
105 }
106
107 _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) volatile _NOEXCEPT { return fetch_add(1); }
108 _LIBCPP_HIDE_FROM_ABI _Tp* operator++(int) _NOEXCEPT { return fetch_add(1); }
109 _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) volatile _NOEXCEPT { return fetch_sub(1); }
110 _LIBCPP_HIDE_FROM_ABI _Tp* operator--(int) _NOEXCEPT { return fetch_sub(1); }
111 _LIBCPP_HIDE_FROM_ABI _Tp* operator++() volatile _NOEXCEPT { return fetch_add(1) + 1; }
112 _LIBCPP_HIDE_FROM_ABI _Tp* operator++() _NOEXCEPT { return fetch_add(1) + 1; }
113 _LIBCPP_HIDE_FROM_ABI _Tp* operator--() volatile _NOEXCEPT { return fetch_sub(1) - 1; }
114 _LIBCPP_HIDE_FROM_ABI _Tp* operator--() _NOEXCEPT { return fetch_sub(1) - 1; }
115 _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_add(__op) + __op; }
116 _LIBCPP_HIDE_FROM_ABI _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT { return fetch_add(__op) + __op; }
117 _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT { return fetch_sub(__op) - __op; }
118 _LIBCPP_HIDE_FROM_ABI _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT { return fetch_sub(__op) - __op; }
119
120 atomic& operator=(const atomic&) = delete;
121 atomic& operator=(const atomic&) volatile = delete;
122};
123
124#if _LIBCPP_STD_VER >= 20
125template <class _Tp>
126 requires is_floating_point_v<_Tp>
127struct atomic<_Tp> : __atomic_base<_Tp> {
128private:
129 _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_fp80_long_double() {
130 // Only x87-fp80 long double has 64-bit mantissa
131 return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>;
132 }
133
134 _LIBCPP_HIDE_FROM_ABI static constexpr bool __has_rmw_builtin() {
135# ifndef _LIBCPP_COMPILER_CLANG_BASED
136 return false;
137# else
138 // The builtin __cxx_atomic_fetch_add errors during compilation for
139 // long double on platforms with fp80 format.
140 // For more details, see
141 // lib/Sema/SemaChecking.cpp function IsAllowedValueType
142 // LLVM Parser does not allow atomicrmw with x86_fp80 type.
143 // if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
144 // &Context.getTargetInfo().getLongDoubleFormat() ==
145 // &llvm::APFloat::x87DoubleExtended())
146 // For more info
147 // https://github.com/llvm/llvm-project/issues/68602
148 // https://reviews.llvm.org/D53965
149 return !__is_fp80_long_double();
150# endif
151 }
152
153 template <class _This, class _Operation, class _BuiltinOp>
154 _LIBCPP_HIDE_FROM_ABI static _Tp
155 __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) {
156 if constexpr (__has_rmw_builtin()) {
157 return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m);
158 } else {
159 _Tp __old = __self.load(memory_order_relaxed);
160 _Tp __new = __operation(__old, __operand);
161 while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) {
162# ifdef _LIBCPP_COMPILER_CLANG_BASED
163 if constexpr (__is_fp80_long_double()) {
164 // https://github.com/llvm/llvm-project/issues/47978
165 // clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak
166 // Note __old = __self.load(memory_order_relaxed) will not work
167 std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed);
168 }
169# endif
170 __new = __operation(__old, __operand);
171 }
172 return __old;
173 }
174 }
175
176 template <class _This>
177 _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) {
178 auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
179 return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order);
180 };
181 return __rmw_op(std::forward<_This>(__self), __operand, __m, std::plus<>{}, __builtin_op);
182 }
183
184 template <class _This>
185 _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) {
186 auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
187 return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order);
188 };
189 return __rmw_op(std::forward<_This>(__self), __operand, __m, std::minus<>{}, __builtin_op);
190 }
191
192public:
193 using __base = __atomic_base<_Tp>;
194 using value_type = _Tp;
195 using difference_type = value_type;
196
197 _LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default;
198 _LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {}
199
200 atomic(const atomic&) = delete;
201 atomic& operator=(const atomic&) = delete;
202 atomic& operator=(const atomic&) volatile = delete;
203
204 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept
205 requires __base::is_always_lock_free
206 {
207 __base::store(__d);
208 return __d;
209 }
210 _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept {
211 __base::store(__d);
212 return __d;
213 }
214
215 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
216 requires __base::is_always_lock_free
217 {
218 return __fetch_add(*this, __op, __m);
219 }
220
221 _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
222 return __fetch_add(*this, __op, __m);
223 }
224
225 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
226 requires __base::is_always_lock_free
227 {
228 return __fetch_sub(*this, __op, __m);
229 }
230
231 _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
232 return __fetch_sub(*this, __op, __m);
233 }
234
235 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept
236 requires __base::is_always_lock_free
237 {
238 return fetch_add(__op) + __op;
239 }
240
241 _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; }
242
243 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept
244 requires __base::is_always_lock_free
245 {
246 return fetch_sub(__op) - __op;
247 }
248
249 _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; }
250};
251
252#endif // _LIBCPP_STD_VER >= 20
253
254// atomic_is_lock_free
255
256template <class _Tp>
257_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT {
258 return __o->is_lock_free();
259}
260
261template <class _Tp>
262_LIBCPP_HIDE_FROM_ABI bool atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT {
263 return __o->is_lock_free();
264}
265
266// atomic_init
267
268template <class _Tp>
269_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
270atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
271 std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
272}
273
274template <class _Tp>
275_LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI void
276atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
277 std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
278}
279
280// atomic_store
281
282template <class _Tp>
283_LIBCPP_HIDE_FROM_ABI void atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
284 __o->store(__d);
285}
286
287template <class _Tp>
288_LIBCPP_HIDE_FROM_ABI void atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
289 __o->store(__d);
290}
291
292// atomic_store_explicit
293
294template <class _Tp>
295_LIBCPP_HIDE_FROM_ABI void
296atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
297 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
298 __o->store(__d, __m);
299}
300
301template <class _Tp>
302_LIBCPP_HIDE_FROM_ABI void
303atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
304 _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m) {
305 __o->store(__d, __m);
306}
307
308// atomic_load
309
310template <class _Tp>
311_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT {
312 return __o->load();
313}
314
315template <class _Tp>
316_LIBCPP_HIDE_FROM_ABI _Tp atomic_load(const atomic<_Tp>* __o) _NOEXCEPT {
317 return __o->load();
318}
319
320// atomic_load_explicit
321
322template <class _Tp>
323_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
324 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
325 return __o->load(__m);
326}
327
328template <class _Tp>
329_LIBCPP_HIDE_FROM_ABI _Tp atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
330 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
331 return __o->load(__m);
332}
333
334// atomic_exchange
335
336template <class _Tp>
337_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
338 return __o->exchange(__d);
339}
340
341template <class _Tp>
342_LIBCPP_HIDE_FROM_ABI _Tp atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
343 return __o->exchange(__d);
344}
345
346// atomic_exchange_explicit
347
348template <class _Tp>
349_LIBCPP_HIDE_FROM_ABI _Tp
350atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {
351 return __o->exchange(__d, __m);
352}
353
354template <class _Tp>
355_LIBCPP_HIDE_FROM_ABI _Tp
356atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT {
357 return __o->exchange(__d, __m);
358}
359
360// atomic_compare_exchange_weak
361
362template <class _Tp>
363_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(
364 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
365 return __o->compare_exchange_weak(*__e, __d);
366}
367
368template <class _Tp>
369_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak(
370 atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
371 return __o->compare_exchange_weak(*__e, __d);
372}
373
374// atomic_compare_exchange_strong
375
376template <class _Tp>
377_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(
378 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
379 return __o->compare_exchange_strong(*__e, __d);
380}
381
382template <class _Tp>
383_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong(
384 atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT {
385 return __o->compare_exchange_strong(*__e, __d);
386}
387
388// atomic_compare_exchange_weak_explicit
389
390template <class _Tp>
391_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(
392 volatile atomic<_Tp>* __o,
393 typename atomic<_Tp>::value_type* __e,
394 typename atomic<_Tp>::value_type __d,
395 memory_order __s,
396 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
397 return __o->compare_exchange_weak(*__e, __d, __s, __f);
398}
399
400template <class _Tp>
401_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_weak_explicit(
402 atomic<_Tp>* __o,
403 typename atomic<_Tp>::value_type* __e,
404 typename atomic<_Tp>::value_type __d,
405 memory_order __s,
406 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
407 return __o->compare_exchange_weak(*__e, __d, __s, __f);
408}
409
410// atomic_compare_exchange_strong_explicit
411
412template <class _Tp>
413_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
414 volatile atomic<_Tp>* __o,
415 typename atomic<_Tp>::value_type* __e,
416 typename atomic<_Tp>::value_type __d,
417 memory_order __s,
418 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
419 return __o->compare_exchange_strong(*__e, __d, __s, __f);
420}
421
422template <class _Tp>
423_LIBCPP_HIDE_FROM_ABI bool atomic_compare_exchange_strong_explicit(
424 atomic<_Tp>* __o,
425 typename atomic<_Tp>::value_type* __e,
426 typename atomic<_Tp>::value_type __d,
427 memory_order __s,
428 memory_order __f) _NOEXCEPT _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f) {
429 return __o->compare_exchange_strong(*__e, __d, __s, __f);
430}
431
432// atomic_wait
433
434template <class _Tp>
435_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
436atomic_wait(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
437 return __o->wait(__v);
438}
439
440template <class _Tp>
441_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
442atomic_wait(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v) _NOEXCEPT {
443 return __o->wait(__v);
444}
445
446// atomic_wait_explicit
447
448template <class _Tp>
449_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
450atomic_wait_explicit(const volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
451 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
452 return __o->wait(__v, __m);
453}
454
455template <class _Tp>
456_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
457atomic_wait_explicit(const atomic<_Tp>* __o, typename atomic<_Tp>::value_type __v, memory_order __m) _NOEXCEPT
458 _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m) {
459 return __o->wait(__v, __m);
460}
461
462// atomic_notify_one
463
464template <class _Tp>
465_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
466atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT {
467 __o->notify_one();
468}
469template <class _Tp>
470_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
471atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT {
472 __o->notify_one();
473}
474
475// atomic_notify_all
476
477template <class _Tp>
478_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
479atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT {
480 __o->notify_all();
481}
482template <class _Tp>
483_LIBCPP_DEPRECATED_ATOMIC_SYNC _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
484atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT {
485 __o->notify_all();
486}
487
488// atomic_fetch_add
489
490template <class _Tp>
491_LIBCPP_HIDE_FROM_ABI _Tp
492atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
493 return __o->fetch_add(__op);
494}
495
496template <class _Tp>
497_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
498 return __o->fetch_add(__op);
499}
500
501// atomic_fetch_add_explicit
502
503template <class _Tp>
504_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_add_explicit(
505 volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
506 return __o->fetch_add(__op, __m);
507}
508
509template <class _Tp>
510_LIBCPP_HIDE_FROM_ABI _Tp
511atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
512 return __o->fetch_add(__op, __m);
513}
514
515// atomic_fetch_sub
516
517template <class _Tp>
518_LIBCPP_HIDE_FROM_ABI _Tp
519atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
520 return __o->fetch_sub(__op);
521}
522
523template <class _Tp>
524_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT {
525 return __o->fetch_sub(__op);
526}
527
528// atomic_fetch_sub_explicit
529
530template <class _Tp>
531_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_sub_explicit(
532 volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
533 return __o->fetch_sub(__op, __m);
534}
535
536template <class _Tp>
537_LIBCPP_HIDE_FROM_ABI _Tp
538atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT {
539 return __o->fetch_sub(__op, __m);
540}
541
542// atomic_fetch_and
543
544template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
545_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
546 return __o->fetch_and(__op);
547}
548
549template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
550_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
551 return __o->fetch_and(__op);
552}
553
554// atomic_fetch_and_explicit
555
556template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
557_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_and_explicit(
558 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
559 return __o->fetch_and(__op, __m);
560}
561
562template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
563_LIBCPP_HIDE_FROM_ABI _Tp
564atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
565 return __o->fetch_and(__op, __m);
566}
567
568// atomic_fetch_or
569
570template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
571_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
572 return __o->fetch_or(__op);
573}
574
575template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
576_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
577 return __o->fetch_or(__op);
578}
579
580// atomic_fetch_or_explicit
581
582template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
583_LIBCPP_HIDE_FROM_ABI _Tp
584atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
585 return __o->fetch_or(__op, __m);
586}
587
588template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
589_LIBCPP_HIDE_FROM_ABI _Tp
590atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
591 return __o->fetch_or(__op, __m);
592}
593
594// atomic_fetch_xor
595
596template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
597_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
598 return __o->fetch_xor(__op);
599}
600
601template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
602_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT {
603 return __o->fetch_xor(__op);
604}
605
606// atomic_fetch_xor_explicit
607
608template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
609_LIBCPP_HIDE_FROM_ABI _Tp atomic_fetch_xor_explicit(
610 volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
611 return __o->fetch_xor(__op, __m);
612}
613
614template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
615_LIBCPP_HIDE_FROM_ABI _Tp
616atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT {
617 return __o->fetch_xor(__op, __m);
618}
619
620_LIBCPP_END_NAMESPACE_STD
621
622#endif // _LIBCPP___ATOMIC_ATOMIC_H
623