xref: /freebsd/contrib/llvm-project/libcxx/include/__atomic/atomic.h (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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 <__memory/addressof.h>
18 #include <__type_traits/is_function.h>
19 #include <__type_traits/is_same.h>
20 #include <__type_traits/remove_pointer.h>
21 #include <cstddef>
22 
23 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
24 #  pragma GCC system_header
25 #endif
26 
27 _LIBCPP_BEGIN_NAMESPACE_STD
28 
29 template <class _Tp>
30 struct atomic
31     : public __atomic_base<_Tp>
32 {
33   using __base          = __atomic_base<_Tp>;
34   using value_type      = _Tp;
35   using difference_type = value_type;
36 
37 #if _LIBCPP_STD_VER >= 20
38     _LIBCPP_HIDE_FROM_ABI
39     atomic() = default;
40 #else
41     _LIBCPP_HIDE_FROM_ABI
42     atomic() _NOEXCEPT = default;
43 #endif
44 
45     _LIBCPP_HIDE_FROM_ABI
46     _LIBCPP_CONSTEXPR atomic(_Tp __d) _NOEXCEPT : __base(__d) {}
47 
48     _LIBCPP_HIDE_FROM_ABI
49     _Tp operator=(_Tp __d) volatile _NOEXCEPT
50         {__base::store(__d); return __d;}
51     _LIBCPP_HIDE_FROM_ABI
52     _Tp operator=(_Tp __d) _NOEXCEPT
53         {__base::store(__d); return __d;}
54 
55     atomic& operator=(const atomic&) = delete;
56     atomic& operator=(const atomic&) volatile = delete;
57 };
58 
59 // atomic<T*>
60 
61 template <class _Tp>
62 struct atomic<_Tp*>
63     : public __atomic_base<_Tp*>
64 {
65     using __base          = __atomic_base<_Tp*>;
66     using value_type      = _Tp*;
67     using difference_type = ptrdiff_t;
68 
69     _LIBCPP_HIDE_FROM_ABI
70     atomic() _NOEXCEPT = default;
71 
72     _LIBCPP_HIDE_FROM_ABI
73     _LIBCPP_CONSTEXPR atomic(_Tp* __d) _NOEXCEPT : __base(__d) {}
74 
75     _LIBCPP_HIDE_FROM_ABI
76     _Tp* operator=(_Tp* __d) volatile _NOEXCEPT
77         {__base::store(__d); return __d;}
78     _LIBCPP_HIDE_FROM_ABI
79     _Tp* operator=(_Tp* __d) _NOEXCEPT
80         {__base::store(__d); return __d;}
81 
82     _LIBCPP_HIDE_FROM_ABI
83     _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
90     _Tp* fetch_add(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
91         // __atomic_fetch_add accepts function pointers, guard against them.
92         static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
93         return std::__cxx_atomic_fetch_add(std::addressof(this->__a_), __op, __m);
94     }
95 
96     _LIBCPP_HIDE_FROM_ABI
97     _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) volatile _NOEXCEPT {
98         // __atomic_fetch_add accepts function pointers, guard against them.
99         static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
100         return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
101     }
102 
103     _LIBCPP_HIDE_FROM_ABI
104     _Tp* fetch_sub(ptrdiff_t __op, memory_order __m = memory_order_seq_cst) _NOEXCEPT {
105         // __atomic_fetch_add accepts function pointers, guard against them.
106         static_assert(!is_function<__remove_pointer_t<_Tp> >::value, "Pointer to function isn't allowed");
107         return std::__cxx_atomic_fetch_sub(std::addressof(this->__a_), __op, __m);
108     }
109 
110     _LIBCPP_HIDE_FROM_ABI
111     _Tp* operator++(int) volatile _NOEXCEPT            {return fetch_add(1);}
112     _LIBCPP_HIDE_FROM_ABI
113     _Tp* operator++(int) _NOEXCEPT                     {return fetch_add(1);}
114     _LIBCPP_HIDE_FROM_ABI
115     _Tp* operator--(int) volatile _NOEXCEPT            {return fetch_sub(1);}
116     _LIBCPP_HIDE_FROM_ABI
117     _Tp* operator--(int) _NOEXCEPT                     {return fetch_sub(1);}
118     _LIBCPP_HIDE_FROM_ABI
119     _Tp* operator++() volatile _NOEXCEPT               {return fetch_add(1) + 1;}
120     _LIBCPP_HIDE_FROM_ABI
121     _Tp* operator++() _NOEXCEPT                        {return fetch_add(1) + 1;}
122     _LIBCPP_HIDE_FROM_ABI
123     _Tp* operator--() volatile _NOEXCEPT               {return fetch_sub(1) - 1;}
124     _LIBCPP_HIDE_FROM_ABI
125     _Tp* operator--() _NOEXCEPT                        {return fetch_sub(1) - 1;}
126     _LIBCPP_HIDE_FROM_ABI
127     _Tp* operator+=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_add(__op) + __op;}
128     _LIBCPP_HIDE_FROM_ABI
129     _Tp* operator+=(ptrdiff_t __op) _NOEXCEPT          {return fetch_add(__op) + __op;}
130     _LIBCPP_HIDE_FROM_ABI
131     _Tp* operator-=(ptrdiff_t __op) volatile _NOEXCEPT {return fetch_sub(__op) - __op;}
132     _LIBCPP_HIDE_FROM_ABI
133     _Tp* operator-=(ptrdiff_t __op) _NOEXCEPT          {return fetch_sub(__op) - __op;}
134 
135     atomic& operator=(const atomic&) = delete;
136     atomic& operator=(const atomic&) volatile = delete;
137 };
138 
139 // atomic_is_lock_free
140 
141 template <class _Tp>
142 _LIBCPP_HIDE_FROM_ABI
143 bool
144 atomic_is_lock_free(const volatile atomic<_Tp>* __o) _NOEXCEPT
145 {
146     return __o->is_lock_free();
147 }
148 
149 template <class _Tp>
150 _LIBCPP_HIDE_FROM_ABI
151 bool
152 atomic_is_lock_free(const atomic<_Tp>* __o) _NOEXCEPT
153 {
154     return __o->is_lock_free();
155 }
156 
157 // atomic_init
158 
159 template <class _Tp>
160 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI
161 void
162 atomic_init(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
163 {
164     std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
165 }
166 
167 template <class _Tp>
168 _LIBCPP_DEPRECATED_IN_CXX20 _LIBCPP_HIDE_FROM_ABI
169 void
170 atomic_init(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
171 {
172     std::__cxx_atomic_init(std::addressof(__o->__a_), __d);
173 }
174 
175 // atomic_store
176 
177 template <class _Tp>
178 _LIBCPP_HIDE_FROM_ABI
179 void
180 atomic_store(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
181 {
182     __o->store(__d);
183 }
184 
185 template <class _Tp>
186 _LIBCPP_HIDE_FROM_ABI
187 void
188 atomic_store(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
189 {
190     __o->store(__d);
191 }
192 
193 // atomic_store_explicit
194 
195 template <class _Tp>
196 _LIBCPP_HIDE_FROM_ABI
197 void
198 atomic_store_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
199   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m)
200 {
201     __o->store(__d, __m);
202 }
203 
204 template <class _Tp>
205 _LIBCPP_HIDE_FROM_ABI
206 void
207 atomic_store_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
208   _LIBCPP_CHECK_STORE_MEMORY_ORDER(__m)
209 {
210     __o->store(__d, __m);
211 }
212 
213 // atomic_load
214 
215 template <class _Tp>
216 _LIBCPP_HIDE_FROM_ABI
217 _Tp
218 atomic_load(const volatile atomic<_Tp>* __o) _NOEXCEPT
219 {
220     return __o->load();
221 }
222 
223 template <class _Tp>
224 _LIBCPP_HIDE_FROM_ABI
225 _Tp
226 atomic_load(const atomic<_Tp>* __o) _NOEXCEPT
227 {
228     return __o->load();
229 }
230 
231 // atomic_load_explicit
232 
233 template <class _Tp>
234 _LIBCPP_HIDE_FROM_ABI
235 _Tp
236 atomic_load_explicit(const volatile atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
237   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
238 {
239     return __o->load(__m);
240 }
241 
242 template <class _Tp>
243 _LIBCPP_HIDE_FROM_ABI
244 _Tp
245 atomic_load_explicit(const atomic<_Tp>* __o, memory_order __m) _NOEXCEPT
246   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
247 {
248     return __o->load(__m);
249 }
250 
251 // atomic_exchange
252 
253 template <class _Tp>
254 _LIBCPP_HIDE_FROM_ABI
255 _Tp
256 atomic_exchange(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
257 {
258     return __o->exchange(__d);
259 }
260 
261 template <class _Tp>
262 _LIBCPP_HIDE_FROM_ABI
263 _Tp
264 atomic_exchange(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d) _NOEXCEPT
265 {
266     return __o->exchange(__d);
267 }
268 
269 // atomic_exchange_explicit
270 
271 template <class _Tp>
272 _LIBCPP_HIDE_FROM_ABI
273 _Tp
274 atomic_exchange_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
275 {
276     return __o->exchange(__d, __m);
277 }
278 
279 template <class _Tp>
280 _LIBCPP_HIDE_FROM_ABI
281 _Tp
282 atomic_exchange_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __d, memory_order __m) _NOEXCEPT
283 {
284     return __o->exchange(__d, __m);
285 }
286 
287 // atomic_compare_exchange_weak
288 
289 template <class _Tp>
290 _LIBCPP_HIDE_FROM_ABI
291 bool
292 atomic_compare_exchange_weak(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
293 {
294     return __o->compare_exchange_weak(*__e, __d);
295 }
296 
297 template <class _Tp>
298 _LIBCPP_HIDE_FROM_ABI
299 bool
300 atomic_compare_exchange_weak(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
301 {
302     return __o->compare_exchange_weak(*__e, __d);
303 }
304 
305 // atomic_compare_exchange_strong
306 
307 template <class _Tp>
308 _LIBCPP_HIDE_FROM_ABI
309 bool
310 atomic_compare_exchange_strong(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
311 {
312     return __o->compare_exchange_strong(*__e, __d);
313 }
314 
315 template <class _Tp>
316 _LIBCPP_HIDE_FROM_ABI
317 bool
318 atomic_compare_exchange_strong(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d) _NOEXCEPT
319 {
320     return __o->compare_exchange_strong(*__e, __d);
321 }
322 
323 // atomic_compare_exchange_weak_explicit
324 
325 template <class _Tp>
326 _LIBCPP_HIDE_FROM_ABI
327 bool
328 atomic_compare_exchange_weak_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e,
329                                       typename atomic<_Tp>::value_type __d,
330                                       memory_order __s, memory_order __f) _NOEXCEPT
331   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
332 {
333     return __o->compare_exchange_weak(*__e, __d, __s, __f);
334 }
335 
336 template <class _Tp>
337 _LIBCPP_HIDE_FROM_ABI
338 bool
339 atomic_compare_exchange_weak_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d,
340                                       memory_order __s, memory_order __f) _NOEXCEPT
341   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
342 {
343     return __o->compare_exchange_weak(*__e, __d, __s, __f);
344 }
345 
346 // atomic_compare_exchange_strong_explicit
347 
348 template <class _Tp>
349 _LIBCPP_HIDE_FROM_ABI
350 bool
351 atomic_compare_exchange_strong_explicit(volatile atomic<_Tp>* __o,
352                                         typename atomic<_Tp>::value_type* __e, typename atomic<_Tp>::value_type __d,
353                                         memory_order __s, memory_order __f) _NOEXCEPT
354   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
355 {
356     return __o->compare_exchange_strong(*__e, __d, __s, __f);
357 }
358 
359 template <class _Tp>
360 _LIBCPP_HIDE_FROM_ABI
361 bool
362 atomic_compare_exchange_strong_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type* __e,
363                                         typename atomic<_Tp>::value_type __d,
364                                         memory_order __s, memory_order __f) _NOEXCEPT
365   _LIBCPP_CHECK_EXCHANGE_MEMORY_ORDER(__s, __f)
366 {
367     return __o->compare_exchange_strong(*__e, __d, __s, __f);
368 }
369 
370 // atomic_wait
371 
372 template <class _Tp>
373 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
374 void atomic_wait(const volatile atomic<_Tp>* __o,
375                  typename atomic<_Tp>::value_type __v) _NOEXCEPT
376 {
377     return __o->wait(__v);
378 }
379 
380 template <class _Tp>
381 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
382 void atomic_wait(const atomic<_Tp>* __o,
383                  typename atomic<_Tp>::value_type __v) _NOEXCEPT
384 {
385     return __o->wait(__v);
386 }
387 
388 // atomic_wait_explicit
389 
390 template <class _Tp>
391 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
392 void atomic_wait_explicit(const volatile atomic<_Tp>* __o,
393                           typename atomic<_Tp>::value_type __v,
394                           memory_order __m) _NOEXCEPT
395   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
396 {
397     return __o->wait(__v, __m);
398 }
399 
400 template <class _Tp>
401 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
402 void atomic_wait_explicit(const atomic<_Tp>* __o,
403                           typename atomic<_Tp>::value_type __v,
404                           memory_order __m) _NOEXCEPT
405   _LIBCPP_CHECK_LOAD_MEMORY_ORDER(__m)
406 {
407     return __o->wait(__v, __m);
408 }
409 
410 // atomic_notify_one
411 
412 template <class _Tp>
413 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
414 void atomic_notify_one(volatile atomic<_Tp>* __o) _NOEXCEPT
415 {
416     __o->notify_one();
417 }
418 template <class _Tp>
419 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
420 void atomic_notify_one(atomic<_Tp>* __o) _NOEXCEPT
421 {
422     __o->notify_one();
423 }
424 
425 // atomic_notify_all
426 
427 template <class _Tp>
428 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
429 void atomic_notify_all(volatile atomic<_Tp>* __o) _NOEXCEPT
430 {
431     __o->notify_all();
432 }
433 template <class _Tp>
434 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
435 void atomic_notify_all(atomic<_Tp>* __o) _NOEXCEPT
436 {
437     __o->notify_all();
438 }
439 
440 // atomic_fetch_add
441 
442 template <class _Tp>
443 _LIBCPP_HIDE_FROM_ABI
444 _Tp
445 atomic_fetch_add(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
446 {
447     return __o->fetch_add(__op);
448 }
449 
450 template <class _Tp>
451 _LIBCPP_HIDE_FROM_ABI
452 _Tp
453 atomic_fetch_add(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
454 {
455     return __o->fetch_add(__op);
456 }
457 
458 // atomic_fetch_add_explicit
459 
460 template <class _Tp>
461 _LIBCPP_HIDE_FROM_ABI
462 _Tp atomic_fetch_add_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
463 {
464     return __o->fetch_add(__op, __m);
465 }
466 
467 template <class _Tp>
468 _LIBCPP_HIDE_FROM_ABI
469 _Tp atomic_fetch_add_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
470 {
471     return __o->fetch_add(__op, __m);
472 }
473 
474 // atomic_fetch_sub
475 
476 template <class _Tp>
477 _LIBCPP_HIDE_FROM_ABI
478 _Tp atomic_fetch_sub(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
479 {
480     return __o->fetch_sub(__op);
481 }
482 
483 template <class _Tp>
484 _LIBCPP_HIDE_FROM_ABI
485 _Tp atomic_fetch_sub(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op) _NOEXCEPT
486 {
487     return __o->fetch_sub(__op);
488 }
489 
490 // atomic_fetch_sub_explicit
491 
492 template <class _Tp>
493 _LIBCPP_HIDE_FROM_ABI
494 _Tp atomic_fetch_sub_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
495 {
496     return __o->fetch_sub(__op, __m);
497 }
498 
499 template <class _Tp>
500 _LIBCPP_HIDE_FROM_ABI
501 _Tp atomic_fetch_sub_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::difference_type __op, memory_order __m) _NOEXCEPT
502 {
503     return __o->fetch_sub(__op, __m);
504 }
505 
506 // atomic_fetch_and
507 
508 template <class _Tp>
509 _LIBCPP_HIDE_FROM_ABI
510 typename enable_if
511 <
512     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
513     _Tp
514 >::type
515 atomic_fetch_and(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
516 {
517     return __o->fetch_and(__op);
518 }
519 
520 template <class _Tp>
521 _LIBCPP_HIDE_FROM_ABI
522 typename enable_if
523 <
524     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
525     _Tp
526 >::type
527 atomic_fetch_and(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
528 {
529     return __o->fetch_and(__op);
530 }
531 
532 // atomic_fetch_and_explicit
533 
534 template <class _Tp>
535 _LIBCPP_HIDE_FROM_ABI
536 typename enable_if
537 <
538     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
539     _Tp
540 >::type
541 atomic_fetch_and_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
542 {
543     return __o->fetch_and(__op, __m);
544 }
545 
546 template <class _Tp>
547 _LIBCPP_HIDE_FROM_ABI
548 typename enable_if
549 <
550     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
551     _Tp
552 >::type
553 atomic_fetch_and_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
554 {
555     return __o->fetch_and(__op, __m);
556 }
557 
558 // atomic_fetch_or
559 
560 template <class _Tp>
561 _LIBCPP_HIDE_FROM_ABI
562 typename enable_if
563 <
564     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
565     _Tp
566 >::type
567 atomic_fetch_or(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
568 {
569     return __o->fetch_or(__op);
570 }
571 
572 template <class _Tp>
573 _LIBCPP_HIDE_FROM_ABI
574 typename enable_if
575 <
576     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
577     _Tp
578 >::type
579 atomic_fetch_or(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
580 {
581     return __o->fetch_or(__op);
582 }
583 
584 // atomic_fetch_or_explicit
585 
586 template <class _Tp>
587 _LIBCPP_HIDE_FROM_ABI
588 typename enable_if
589 <
590     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
591     _Tp
592 >::type
593 atomic_fetch_or_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
594 {
595     return __o->fetch_or(__op, __m);
596 }
597 
598 template <class _Tp>
599 _LIBCPP_HIDE_FROM_ABI
600 typename enable_if
601 <
602     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
603     _Tp
604 >::type
605 atomic_fetch_or_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
606 {
607     return __o->fetch_or(__op, __m);
608 }
609 
610 // atomic_fetch_xor
611 
612 template <class _Tp>
613 _LIBCPP_HIDE_FROM_ABI
614 typename enable_if
615 <
616     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
617     _Tp
618 >::type
619 atomic_fetch_xor(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
620 {
621     return __o->fetch_xor(__op);
622 }
623 
624 template <class _Tp>
625 _LIBCPP_HIDE_FROM_ABI
626 typename enable_if
627 <
628     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
629     _Tp
630 >::type
631 atomic_fetch_xor(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op) _NOEXCEPT
632 {
633     return __o->fetch_xor(__op);
634 }
635 
636 // atomic_fetch_xor_explicit
637 
638 template <class _Tp>
639 _LIBCPP_HIDE_FROM_ABI
640 typename enable_if
641 <
642     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
643     _Tp
644 >::type
645 atomic_fetch_xor_explicit(volatile atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
646 {
647     return __o->fetch_xor(__op, __m);
648 }
649 
650 template <class _Tp>
651 _LIBCPP_HIDE_FROM_ABI
652 typename enable_if
653 <
654     is_integral<_Tp>::value && !is_same<_Tp, bool>::value,
655     _Tp
656 >::type
657 atomic_fetch_xor_explicit(atomic<_Tp>* __o, typename atomic<_Tp>::value_type __op, memory_order __m) _NOEXCEPT
658 {
659     return __o->fetch_xor(__op, __m);
660 }
661 
662 _LIBCPP_END_NAMESPACE_STD
663 
664 #endif // _LIBCPP___ATOMIC_ATOMIC_H
665