• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
35 template <class _Tp>
36 struct atomic
37     : public __atomic_base<_Tp>
38 {
39   using __base          = __atomic_base<_Tp>;
40   using value_type      = _Tp;
41   using difference_type = value_type;
42 
43 #if _LIBCPP_STD_VER >= 20
44     _LIBCPP_HIDE_FROM_ABI
45     atomic() = default;
46 #else
47     _LIBCPP_HIDE_FROM_ABI
48     atomic() _NOEXCEPT = default;
49 #endif
50 
51     _LIBCPP_HIDE_FROM_ABI
atomicatomic52     _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
53 
54     _LIBCPP_HIDE_FROM_ABI
55     _Tp operator=(_Tp __d) volatile _NOEXCEPT
56         {__base::store(__d); return __d;}
57     _LIBCPP_HIDE_FROM_ABI
58     _Tp operator=(_Tp __d) _NOEXCEPT
59         {__base::store(__d); return __d;}
60 
61     atomic& operator=(const atomic&) = delete;
62     atomic& operator=(const atomic&) volatile = delete;
63 };
64 
65 // atomic<T*>
66 
67 template <class _Tp>
68 struct atomic<_Tp*>
69     : public __atomic_base<_Tp*>
70 {
71     using __base          = __atomic_base<_Tp*>;
72     using value_type      = _Tp*;
73     using difference_type = ptrdiff_t;
74 
75     _LIBCPP_HIDE_FROM_ABI
76     atomic() _NOEXCEPT = default;
77 
78     _LIBCPP_HIDE_FROM_ABI
79     _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
80 
81     _LIBCPP_HIDE_FROM_ABI
82     _Tp* operator=(_Tp* __d) volatile _NOEXCEPT
83         {__base::store(__d); return __d;}
84     _LIBCPP_HIDE_FROM_ABI
85     _Tp* operator=(_Tp* __d) _NOEXCEPT
86         {__base::store(__d); return __d;}
87 
88     _LIBCPP_HIDE_FROM_ABI
89     _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _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
96     _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
97         // __atomic_fetch_add accepts function pointers, guard against them.
98         static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
99         return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
100     }
101 
102     _LIBCPP_HIDE_FROM_ABI
103     _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
104         // __atomic_fetch_add accepts function pointers, guard against them.
105         static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
106         return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
107     }
108 
109     _LIBCPP_HIDE_FROM_ABI
110     _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
111         // __atomic_fetch_add accepts function pointers, guard against them.
112         static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
113         return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
114     }
115 
116     _LIBCPP_HIDE_FROM_ABI
117     _Tp* operator++(int) volatile _NOEXCEPT            {return fetch_add(1);}
118     _LIBCPP_HIDE_FROM_ABI
119     _Tp* operator++(int) _NOEXCEPT                     {return fetch_add(1);}
120     _LIBCPP_HIDE_FROM_ABI
121     _Tp* operator--(int) volatile _NOEXCEPT            {return fetch_sub(1);}
122     _LIBCPP_HIDE_FROM_ABI
123     _Tp* operator--(int) _NOEXCEPT                     {return fetch_sub(1);}
124     _LIBCPP_HIDE_FROM_ABI
125     _Tp* operator++() volatile _NOEXCEPT               {return fetch_add(1) + 1;}
126     _LIBCPP_HIDE_FROM_ABI
127     _Tp* operator++() _NOEXCEPT                        {return fetch_add(1) + 1;}
128     _LIBCPP_HIDE_FROM_ABI
129     _Tp* operator--() volatile _NOEXCEPT               {return fetch_sub(1) - 1;}
130     _LIBCPP_HIDE_FROM_ABI
131     _Tp* operator--() _NOEXCEPT                        {return fetch_sub(1) - 1;}
132     _LIBCPP_HIDE_FROM_ABI
133     _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;}
134     _LIBCPP_HIDE_FROM_ABI
135     _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT          {return fetch_add(__op) + __op;}
136     _LIBCPP_HIDE_FROM_ABI
137     _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;}
138     _LIBCPP_HIDE_FROM_ABI
139     _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT          {return fetch_sub(__op) - __op;}
140 
141     atomic& operator=(const atomic&) = delete;
142     atomic& operator=(const atomic&) volatile = delete;
143 };
144 
145 #if _LIBCPP_STD_VER >= 20
146 template <class _Tp>
147   requires is_floating_point_v<_Tp>
148 struct atomic<_Tp> : __atomic_base<_Tp> {
149   private:
150     _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_fp80_long_double() {
151         // Only x87-fp80 long double has 64-bit mantissa
152         return __LDBL_MANT_DIG__ == 64 && std::is_same_v<_Tp, long double>;
153     }
154 
155     _LIBCPP_HIDE_FROM_ABI static constexpr bool __has_rmw_builtin() {
156 #  ifndef _LIBCPP_COMPILER_CLANG_BASED
157         return false;
158 #  else
159         // The builtin __cxx_atomic_fetch_add errors during compilation for
160         // long double on platforms with fp80 format.
161         // For more details, see
162         // lib/Sema/SemaChecking.cpp function IsAllowedValueType
163         // LLVM Parser does not allow atomicrmw with x86_fp80 type.
164         // if (ValType->isSpecificBuiltinType(BuiltinType::LongDouble) &&
165         //    &Context.getTargetInfo().getLongDoubleFormat() ==
166         //        &llvm::APFloat::x87DoubleExtended())
167         // For more info
168         // https://github.com/llvm/llvm-project/issues/68602
169         // https://reviews.llvm.org/D53965
170         return !__is_fp80_long_double();
171 #  endif
172     }
173 
174     template <class _This, class _Operation, class _BuiltinOp>
175     _LIBCPP_HIDE_FROM_ABI static _Tp
176     __rmw_op(_This&& __self, _Tp __operand, memory_order __m, _Operation __operation, _BuiltinOp __builtin_op) {
177         if constexpr (__has_rmw_builtin()) {
178           return __builtin_op(std::addressof(std::forward<_This>(__self).__a_), __operand, __m);
179         } else {
180           _Tp __old = __self.load(memory_order_relaxed);
181           _Tp __new = __operation(__old, __operand);
182           while (!__self.compare_exchange_weak(__old, __new, __m, memory_order_relaxed)) {
183 #  ifdef _LIBCPP_COMPILER_CLANG_BASED
184             if constexpr (__is_fp80_long_double()) {
185               // https://github.com/llvm/llvm-project/issues/47978
186               // clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak
187               // Note __old = __self.load(memory_order_relaxed) will not work
188               std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed);
189             }
190 #  endif
191             __new = __operation(__old, __operand);
192           }
193           return __old;
194         }
195     }
196 
197     template <class _This>
198     _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_add(_This&& __self, _Tp __operand, memory_order __m) {
199         auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
200           return std::__cxx_atomic_fetch_add(__a, __builtin_operand, __order);
201         };
202         return __rmw_op(std::forward<_This>(__self), __operand, __m, std::plus<>{}, __builtin_op);
203     }
204 
205     template <class _This>
206     _LIBCPP_HIDE_FROM_ABI static _Tp __fetch_sub(_This&& __self, _Tp __operand, memory_order __m) {
207         auto __builtin_op = [](auto __a, auto __builtin_operand, auto __order) {
208           return std::__cxx_atomic_fetch_sub(__a, __builtin_operand, __order);
209         };
210         return __rmw_op(std::forward<_This>(__self), __operand, __m, std::minus<>{}, __builtin_op);
211     }
212 
213   public:
214     using __base          = __atomic_base<_Tp>;
215     using value_type      = _Tp;
216     using difference_type = value_type;
217 
218     _LIBCPP_HIDE_FROM_ABI constexpr atomic() noexcept = default;
219     _LIBCPP_HIDE_FROM_ABI constexpr atomic(_Tp __d) noexcept : __base(__d) {}
220 
221     atomic(const atomic&)                     = delete;
222     atomic& operator=(const atomic&)          = delete;
223     atomic& operator=(const atomic&) volatile = delete;
224 
225     _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) volatile noexcept
226       requires __base::is_always_lock_free
227     {
228         __base::store(__d);
229         return __d;
230     }
231     _LIBCPP_HIDE_FROM_ABI _Tp operator=(_Tp __d) noexcept {
232         __base::store(__d);
233         return __d;
234     }
235 
236     _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
237       requires __base::is_always_lock_free
238     {
239         return __fetch_add(*this, __op, __m);
240     }
241 
242     _LIBCPP_HIDE_FROM_ABI _Tp fetch_add(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
243         return __fetch_add(*this, __op, __m);
244     }
245 
246     _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) volatile noexcept
247       requires __base::is_always_lock_free
248     {
249         return __fetch_sub(*this, __op, __m);
250     }
251 
252     _LIBCPP_HIDE_FROM_ABI _Tp fetch_sub(_Tp __op, memory_order __m = memory_order_seq_cst) noexcept {
253         return __fetch_sub(*this, __op, __m);
254     }
255 
256     _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) volatile noexcept
257       requires __base::is_always_lock_free
258     {
259         return fetch_add(__op) + __op;
260     }
261 
262     _LIBCPP_HIDE_FROM_ABI _Tp operator+=(_Tp __op) noexcept { return fetch_add(__op) + __op; }
263 
264     _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) volatile noexcept
265       requires __base::is_always_lock_free
266     {
267         return fetch_sub(__op) - __op;
268     }
269 
270     _LIBCPP_HIDE_FROM_ABI _Tp operator-=(_Tp __op) noexcept { return fetch_sub(__op) - __op; }
271 };
272 
273 #endif // _LIBCPP_STD_VER >= 20
274 
275 // atomic_is_lock_free
276 
277 template <class _Tp>
278 _LIBCPP_HIDE_FROM_ABI
279 bool
280 atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT
281 {
282     return __o->is_lock_free();
283 }
284 
285 template <class _Tp>
286 _LIBCPP_HIDE_FROM_ABI
287 bool
288 atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
289 {
290     return __o->is_lock_free();
291 }
292 
293 // atomic_init
294 
295 template <class _Tp>
296 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI
297 void
298 atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
299 {
300     std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
301 }
302 
303 template <class _Tp>
304 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI
305 void
306 atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
307 {
308     std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
309 }
310 
311 // atomic_store
312 
313 template <class _Tp>
314 _LIBCPP_HIDE_FROM_ABI
315 void
316 atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
317 {
318     __o->store(__d);
319 }
320 
321 template <class _Tp>
322 _LIBCPP_HIDE_FROM_ABI
323 void
324 atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
325 {
326     __o->store(__d);
327 }
328 
329 // atomic_store_explicit
330 
331 template <class _Tp>
332 _LIBCPP_HIDE_FROM_ABI
333 void
334 atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
335   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m)
336 {
337     __o->store(__d, __m);
338 }
339 
340 template <class _Tp>
341 _LIBCPP_HIDE_FROM_ABI
342 void
343 atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
344   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m)
345 {
346     __o->store(__d, __m);
347 }
348 
349 // atomic_load
350 
351 template <class _Tp>
352 _LIBCPP_HIDE_FROM_ABI
353 _Tp
354 atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT
355 {
356     return __o->load();
357 }
358 
359 template <class _Tp>
360 _LIBCPP_HIDE_FROM_ABI
361 _Tp
362 atomic_load(const atomic<_Tp>* __o) _NOEXCEPT
363 {
364     return __o->load();
365 }
366 
367 // atomic_load_explicit
368 
369 template <class _Tp>
370 _LIBCPP_HIDE_FROM_ABI
371 _Tp
372 atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
373   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
374 {
375     return __o->load(__m);
376 }
377 
378 template <class _Tp>
379 _LIBCPP_HIDE_FROM_ABI
380 _Tp
381 atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
382   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
383 {
384     return __o->load(__m);
385 }
386 
387 // atomic_exchange
388 
389 template <class _Tp>
390 _LIBCPP_HIDE_FROM_ABI
391 _Tp
392 atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
393 {
394     return __o->exchange(__d);
395 }
396 
397 template <class _Tp>
398 _LIBCPP_HIDE_FROM_ABI
399 _Tp
400 atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
401 {
402     return __o->exchange(__d);
403 }
404 
405 // atomic_exchange_explicit
406 
407 template <class _Tp>
408 _LIBCPP_HIDE_FROM_ABI
409 _Tp
410 atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
411 {
412     return __o->exchange(__d, __m);
413 }
414 
415 template <class _Tp>
416 _LIBCPP_HIDE_FROM_ABI
417 _Tp
418 atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
419 {
420     return __o->exchange(__d, __m);
421 }
422 
423 // atomic_compare_exchange_weak
424 
425 template <class _Tp>
426 _LIBCPP_HIDE_FROM_ABI
427 bool
428 atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
429 {
430     return __o->compare_exchange_weak(*__e, __d);
431 }
432 
433 template <class _Tp>
434 _LIBCPP_HIDE_FROM_ABI
435 bool
436 atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
437 {
438     return __o->compare_exchange_weak(*__e, __d);
439 }
440 
441 // atomic_compare_exchange_strong
442 
443 template <class _Tp>
444 _LIBCPP_HIDE_FROM_ABI
445 bool
446 atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
447 {
448     return __o->compare_exchange_strong(*__e, __d);
449 }
450 
451 template <class _Tp>
452 _LIBCPP_HIDE_FROM_ABI
453 bool
454 atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
455 {
456     return __o->compare_exchange_strong(*__e, __d);
457 }
458 
459 // atomic_compare_exchange_weak_explicit
460 
461 template <class _Tp>
462 _LIBCPP_HIDE_FROM_ABI
463 bool
464 atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e,
465                                       typename atomic<_Tp>::value_type __d,
466                                       memory_order __s, memory_order __f) _NOEXCEPT
467   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
468 {
469     return __o->compare_exchange_weak(*__e, __d, __s, __f);
470 }
471 
472 template <class _Tp>
473 _LIBCPP_HIDE_FROM_ABI
474 bool
475 atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d,
476                                       memory_order __s, memory_order __f) _NOEXCEPT
477   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
478 {
479     return __o->compare_exchange_weak(*__e, __d, __s, __f);
480 }
481 
482 // atomic_compare_exchange_strong_explicit
483 
484 template <class _Tp>
485 _LIBCPP_HIDE_FROM_ABI
486 bool
487 atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o,
488                                         typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d,
489                                         memory_order __s, memory_order __f) _NOEXCEPT
490   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
491 {
492     return __o->compare_exchange_strong(*__e, __d, __s, __f);
493 }
494 
495 template <class _Tp>
496 _LIBCPP_HIDE_FROM_ABI
497 bool
498 atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e,
499                                         typename atomic<_Tp>::value_type __d,
500                                         memory_order __s, memory_order __f) _NOEXCEPT
501   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
502 {
503     return __o->compare_exchange_strong(*__e, __d, __s, __f);
504 }
505 
506 // atomic_wait
507 
508 template <class _Tp>
509 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
510 void atomic_wait(const volatile atomic<_Tp>* __o,
511                  typename atomic<_Tp>::value_type __v) _NOEXCEPT
512 {
513     return __o->wait(__v);
514 }
515 
516 template <class _Tp>
517 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
518 void atomic_wait(const atomic<_Tp>* __o,
519                  typename atomic<_Tp>::value_type __v) _NOEXCEPT
520 {
521     return __o->wait(__v);
522 }
523 
524 // atomic_wait_explicit
525 
526 template <class _Tp>
527 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
528 void atomic_wait_explicit(const volatile atomic<_Tp>* __o,
529                           typename atomic<_Tp>::value_type __v,
530                           memory_order __m) _NOEXCEPT
531   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
532 {
533     return __o->wait(__v, __m);
534 }
535 
536 template <class _Tp>
537 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
538 void atomic_wait_explicit(const atomic<_Tp>* __o,
539                           typename atomic<_Tp>::value_type __v,
540                           memory_order __m) _NOEXCEPT
541   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
542 {
543     return __o->wait(__v, __m);
544 }
545 
546 // atomic_notify_one
547 
548 template <class _Tp>
549 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
550 void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT
551 {
552     __o->notify_one();
553 }
554 template <class _Tp>
555 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
556 void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT
557 {
558     __o->notify_one();
559 }
560 
561 // atomic_notify_all
562 
563 template <class _Tp>
564 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
565 void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT
566 {
567     __o->notify_all();
568 }
569 template <class _Tp>
570 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
571 void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT
572 {
573     __o->notify_all();
574 }
575 
576 // atomic_fetch_add
577 
578 template <class _Tp>
579 _LIBCPP_HIDE_FROM_ABI
580 _Tp
581 atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
582 {
583     return __o->fetch_add(__op);
584 }
585 
586 template <class _Tp>
587 _LIBCPP_HIDE_FROM_ABI
588 _Tp
589 atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
590 {
591     return __o->fetch_add(__op);
592 }
593 
594 // atomic_fetch_add_explicit
595 
596 template <class _Tp>
597 _LIBCPP_HIDE_FROM_ABI
598 _Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
599 {
600     return __o->fetch_add(__op, __m);
601 }
602 
603 template <class _Tp>
604 _LIBCPP_HIDE_FROM_ABI
605 _Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
606 {
607     return __o->fetch_add(__op, __m);
608 }
609 
610 // atomic_fetch_sub
611 
612 template <class _Tp>
613 _LIBCPP_HIDE_FROM_ABI
614 _Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
615 {
616     return __o->fetch_sub(__op);
617 }
618 
619 template <class _Tp>
620 _LIBCPP_HIDE_FROM_ABI
621 _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
622 {
623     return __o->fetch_sub(__op);
624 }
625 
626 // atomic_fetch_sub_explicit
627 
628 template <class _Tp>
629 _LIBCPP_HIDE_FROM_ABI
630 _Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
631 {
632     return __o->fetch_sub(__op, __m);
633 }
634 
635 template <class _Tp>
636 _LIBCPP_HIDE_FROM_ABI
637 _Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
638 {
639     return __o->fetch_sub(__op, __m);
640 }
641 
642 // atomic_fetch_and
643 
644 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
645 _LIBCPP_HIDE_FROM_ABI
646 _Tp
647 atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
648 {
649     return __o->fetch_and(__op);
650 }
651 
652 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
653 _LIBCPP_HIDE_FROM_ABI
654 _Tp
655 atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
656 {
657     return __o->fetch_and(__op);
658 }
659 
660 // atomic_fetch_and_explicit
661 
662 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
663 _LIBCPP_HIDE_FROM_ABI
664 _Tp
665 atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
666 {
667     return __o->fetch_and(__op, __m);
668 }
669 
670 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
671 _LIBCPP_HIDE_FROM_ABI
672 _Tp
673 atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
674 {
675     return __o->fetch_and(__op, __m);
676 }
677 
678 // atomic_fetch_or
679 
680 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
681 _LIBCPP_HIDE_FROM_ABI
682 _Tp
683 atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
684 {
685     return __o->fetch_or(__op);
686 }
687 
688 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
689 _LIBCPP_HIDE_FROM_ABI
690 _Tp
691 atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
692 {
693     return __o->fetch_or(__op);
694 }
695 
696 // atomic_fetch_or_explicit
697 
698 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
699 _LIBCPP_HIDE_FROM_ABI
700 _Tp
701 atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
702 {
703     return __o->fetch_or(__op, __m);
704 }
705 
706 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
707 _LIBCPP_HIDE_FROM_ABI
708 _Tp
709 atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
710 {
711     return __o->fetch_or(__op, __m);
712 }
713 
714 // atomic_fetch_xor
715 
716 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
717 _LIBCPP_HIDE_FROM_ABI
718 _Tp
719 atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
720 {
721     return __o->fetch_xor(__op);
722 }
723 
724 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
725 _LIBCPP_HIDE_FROM_ABI
726 _Tp
727 atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
728 {
729     return __o->fetch_xor(__op);
730 }
731 
732 // atomic_fetch_xor_explicit
733 
734 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
735 _LIBCPP_HIDE_FROM_ABI
736 _Tp
737 atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
738 {
739     return __o->fetch_xor(__op, __m);
740 }
741 
742 template <class _Tp, __enable_if_t<is_integral<_Tp>::value && !is_same<_Tp, bool>::value, int> = 0>
743 _LIBCPP_HIDE_FROM_ABI
744 _Tp
745 atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
746 {
747     return __o->fetch_xor(__op, __m);
748 }
749 
750 _LIBCPP_END_NAMESPACE_STD
751 
752 #endif // _LIBCPP___ATOMIC_ATOMIC_H
753