30#ifndef _GLIBCXX_ATOMIC_BASE_H
31#define _GLIBCXX_ATOMIC_BASE_H 1
34#pragma GCC system_header
42#if __cplusplus > 201703L && _GLIBCXX_HOSTED
46#ifndef _GLIBCXX_ALWAYS_INLINE
47#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__))
52namespace std _GLIBCXX_VISIBILITY(default)
54_GLIBCXX_BEGIN_NAMESPACE_VERSION
64#if __cplusplus > 201703L
68 consume _GLIBCXX26_DEPRECATED = 1,
75 inline constexpr memory_order memory_order_relaxed = memory_order::relaxed;
76 inline constexpr memory_order memory_order_acquire = memory_order::acquire;
77 inline constexpr memory_order memory_order_release = memory_order::release;
78 inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel;
79 inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst;
81#pragma GCC diagnostic push
82#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
84 inline constexpr memory_order memory_order_consume = memory_order::consume;
85#pragma GCC diagnostic pop
99 enum __memory_order_modifier
101 __memory_order_mask = 0x0ffff,
102 __memory_order_modifier_mask = 0xffff0000,
103 __memory_order_hle_acquire = 0x10000,
104 __memory_order_hle_release = 0x20000
126 return __m == memory_order_acq_rel ? memory_order_acquire
127 : __m == memory_order_release ? memory_order_relaxed : __m;
133 return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask)
134 | __memory_order_modifier(__m & __memory_order_modifier_mask));
138 __is_valid_cmpexch_failure_order(
memory_order __m)
noexcept
140 return (__m & __memory_order_mask) != memory_order_release
141 && (__m & __memory_order_mask) != memory_order_acq_rel;
145 template<
typename _IntTp>
146 struct __atomic_base;
150 _GLIBCXX_ALWAYS_INLINE
void
152 { __atomic_thread_fence(
int(__m)); }
154 _GLIBCXX_ALWAYS_INLINE
void
156 { __atomic_signal_fence(
int(__m)); }
159 template<
typename _Tp>
160 _GLIBCXX26_DEPRECATED
169#if __glibcxx_atomic_value_initialization
170# define _GLIBCXX20_INIT(I) = I
172# define _GLIBCXX20_INIT(I)
176#define ATOMIC_VAR_INIT(_VI) { _VI }
178 template<
typename _Tp>
181 template<
typename _Tp>
185#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
186 typedef bool __atomic_flag_data_type;
188 typedef unsigned char __atomic_flag_data_type;
203 _GLIBCXX_BEGIN_EXTERN_C
205 struct __atomic_flag_base
207 __atomic_flag_data_type _M_i _GLIBCXX20_INIT({});
210 _GLIBCXX_END_EXTERN_C
214#define ATOMIC_FLAG_INIT { 0 }
217 struct atomic_flag :
public __atomic_flag_base
219 atomic_flag()
noexcept =
default;
220 ~atomic_flag()
noexcept =
default;
221 atomic_flag(
const atomic_flag&) =
delete;
222 atomic_flag& operator=(
const atomic_flag&) =
delete;
223 atomic_flag& operator=(
const atomic_flag&)
volatile =
delete;
226 constexpr atomic_flag(
bool __i) noexcept
227 : __atomic_flag_base{ _S_init(__i) }
230 _GLIBCXX_ALWAYS_INLINE
bool
231 test_and_set(
memory_order __m = memory_order_seq_cst)
noexcept
233 return __atomic_test_and_set (&_M_i,
int(__m));
236 _GLIBCXX_ALWAYS_INLINE
bool
237 test_and_set(
memory_order __m = memory_order_seq_cst)
volatile noexcept
239 return __atomic_test_and_set (&_M_i,
int(__m));
242#ifdef __glibcxx_atomic_flag_test
243 _GLIBCXX_ALWAYS_INLINE
bool
244 test(
memory_order __m = memory_order_seq_cst)
const noexcept
246 __atomic_flag_data_type __v;
247 __atomic_load(&_M_i, &__v,
int(__m));
248 return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL;
251 _GLIBCXX_ALWAYS_INLINE
bool
252 test(
memory_order __m = memory_order_seq_cst)
const volatile noexcept
254 __atomic_flag_data_type __v;
255 __atomic_load(&_M_i, &__v,
int(__m));
256 return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL;
260#if __glibcxx_atomic_wait
261 _GLIBCXX_ALWAYS_INLINE
void
265 const __atomic_flag_data_type __v
266 = __old ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0;
268 std::__atomic_wait_address_v(&_M_i, __v,
269 [__m,
this] {
return __atomic_load_n(&_M_i,
int(__m)); });
274 _GLIBCXX_ALWAYS_INLINE
void
275 notify_one()
noexcept
276 { std::__atomic_notify_address(&_M_i,
false); }
280 _GLIBCXX_ALWAYS_INLINE
void
281 notify_all()
noexcept
282 { std::__atomic_notify_address(&_M_i,
true); }
287#pragma GCC diagnostic push
288#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
289 _GLIBCXX_ALWAYS_INLINE
void
293 = __m & __memory_order_mask;
294 __glibcxx_assert(__b != memory_order_consume);
295 __glibcxx_assert(__b != memory_order_acquire);
296 __glibcxx_assert(__b != memory_order_acq_rel);
298 __atomic_clear (&_M_i,
int(__m));
301 _GLIBCXX_ALWAYS_INLINE
void
302 clear(
memory_order __m = memory_order_seq_cst)
volatile noexcept
305 = __m & __memory_order_mask;
306 __glibcxx_assert(__b != memory_order_consume);
307 __glibcxx_assert(__b != memory_order_acquire);
308 __glibcxx_assert(__b != memory_order_acq_rel);
310 __atomic_clear (&_M_i,
int(__m));
312#pragma GCC diagnostic pop
315 static constexpr __atomic_flag_data_type
317 {
return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; }
347 namespace __atomic_impl
349 template<
typename _Tp>
350 using _Val =
typename remove_volatile<_Tp>::type;
352#if __glibcxx_atomic_min_max
353 template<
typename _Tp>
355 __fetch_min(_Tp* __ptr, _Val<_Tp> __i,
memory_order __m)
noexcept;
357 template<
typename _Tp>
359 __fetch_max(_Tp* __ptr, _Val<_Tp> __i,
memory_order __m)
noexcept;
363 template<
typename _ITp>
366 using value_type = _ITp;
367 using difference_type = value_type;
370 typedef _ITp __int_type;
372 static constexpr int _S_alignment =
373 sizeof(_ITp) >
alignof(_ITp) ?
sizeof(_ITp) : alignof(_ITp);
375 alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0);
378 __atomic_base() noexcept = default;
379 ~__atomic_base() noexcept = default;
380 __atomic_base(const __atomic_base&) = delete;
381 __atomic_base& operator=(const __atomic_base&) = delete;
382 __atomic_base& operator=(const __atomic_base&) volatile = delete;
384 constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { }
386 operator __int_type() const noexcept
389 operator __int_type() const volatile noexcept
393 operator=(__int_type __i)
noexcept
400 operator=(__int_type __i)
volatile noexcept
407 operator++(
int)
noexcept
408 {
return fetch_add(1); }
411 operator++(
int)
volatile noexcept
412 {
return fetch_add(1); }
415 operator--(
int)
noexcept
416 {
return fetch_sub(1); }
419 operator--(
int)
volatile noexcept
420 {
return fetch_sub(1); }
423 operator++() noexcept
424 {
return __atomic_add_fetch(&_M_i, 1,
int(memory_order_seq_cst)); }
427 operator++() volatile noexcept
428 {
return __atomic_add_fetch(&_M_i, 1,
int(memory_order_seq_cst)); }
431 operator--() noexcept
432 {
return __atomic_sub_fetch(&_M_i, 1,
int(memory_order_seq_cst)); }
435 operator--() volatile noexcept
436 {
return __atomic_sub_fetch(&_M_i, 1,
int(memory_order_seq_cst)); }
439 operator+=(__int_type __i)
noexcept
440 {
return __atomic_add_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
443 operator+=(__int_type __i)
volatile noexcept
444 {
return __atomic_add_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
447 operator-=(__int_type __i)
noexcept
448 {
return __atomic_sub_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
451 operator-=(__int_type __i)
volatile noexcept
452 {
return __atomic_sub_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
455 operator&=(__int_type __i)
noexcept
456 {
return __atomic_and_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
459 operator&=(__int_type __i)
volatile noexcept
460 {
return __atomic_and_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
463 operator|=(__int_type __i)
noexcept
464 {
return __atomic_or_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
467 operator|=(__int_type __i)
volatile noexcept
468 {
return __atomic_or_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
471 operator^=(__int_type __i)
noexcept
472 {
return __atomic_xor_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
475 operator^=(__int_type __i)
volatile noexcept
476 {
return __atomic_xor_fetch(&_M_i, __i,
int(memory_order_seq_cst)); }
479 is_lock_free() const noexcept
482 return __atomic_is_lock_free(
sizeof(_M_i),
483 reinterpret_cast<void *
>(-_S_alignment));
487 is_lock_free() const volatile noexcept
490 return __atomic_is_lock_free(
sizeof(_M_i),
491 reinterpret_cast<void *
>(-_S_alignment));
494#pragma GCC diagnostic push
495#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
496 _GLIBCXX_ALWAYS_INLINE
void
497 store(__int_type __i, memory_order __m = memory_order_seq_cst)
noexcept
500 = __m & __memory_order_mask;
501 __glibcxx_assert(__b != memory_order_acquire);
502 __glibcxx_assert(__b != memory_order_acq_rel);
503 __glibcxx_assert(__b != memory_order_consume);
505 __atomic_store_n(&_M_i, __i,
int(__m));
508 _GLIBCXX_ALWAYS_INLINE
void
509 store(__int_type __i,
510 memory_order __m = memory_order_seq_cst)
volatile noexcept
513 = __m & __memory_order_mask;
514 __glibcxx_assert(__b != memory_order_acquire);
515 __glibcxx_assert(__b != memory_order_acq_rel);
516 __glibcxx_assert(__b != memory_order_consume);
518 __atomic_store_n(&_M_i, __i,
int(__m));
520#pragma GCC diagnostic pop
522 _GLIBCXX_ALWAYS_INLINE __int_type
523 load(memory_order __m = memory_order_seq_cst)
const noexcept
526 = __m & __memory_order_mask;
527 __glibcxx_assert(__b != memory_order_release);
528 __glibcxx_assert(__b != memory_order_acq_rel);
530 return __atomic_load_n(&_M_i,
int(__m));
533 _GLIBCXX_ALWAYS_INLINE __int_type
534 load(memory_order __m = memory_order_seq_cst)
const volatile noexcept
537 = __m & __memory_order_mask;
538 __glibcxx_assert(__b != memory_order_release);
539 __glibcxx_assert(__b != memory_order_acq_rel);
541 return __atomic_load_n(&_M_i,
int(__m));
544 _GLIBCXX_ALWAYS_INLINE __int_type
545 exchange(__int_type __i,
546 memory_order __m = memory_order_seq_cst)
noexcept
548 return __atomic_exchange_n(&_M_i, __i,
int(__m));
552 _GLIBCXX_ALWAYS_INLINE __int_type
553 exchange(__int_type __i,
554 memory_order __m = memory_order_seq_cst)
volatile noexcept
556 return __atomic_exchange_n(&_M_i, __i,
int(__m));
559 _GLIBCXX_ALWAYS_INLINE
bool
560 compare_exchange_weak(__int_type& __i1, __int_type __i2,
561 memory_order __m1, memory_order __m2)
noexcept
563 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
565 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1,
566 int(__m1),
int(__m2));
569 _GLIBCXX_ALWAYS_INLINE
bool
570 compare_exchange_weak(__int_type& __i1, __int_type __i2,
572 memory_order __m2)
volatile noexcept
574 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
576 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1,
577 int(__m1),
int(__m2));
580 _GLIBCXX_ALWAYS_INLINE
bool
581 compare_exchange_weak(__int_type& __i1, __int_type __i2,
582 memory_order __m = memory_order_seq_cst)
noexcept
584 return compare_exchange_weak(__i1, __i2, __m,
585 __cmpexch_failure_order(__m));
588 _GLIBCXX_ALWAYS_INLINE
bool
589 compare_exchange_weak(__int_type& __i1, __int_type __i2,
590 memory_order __m = memory_order_seq_cst)
volatile noexcept
592 return compare_exchange_weak(__i1, __i2, __m,
593 __cmpexch_failure_order(__m));
596 _GLIBCXX_ALWAYS_INLINE
bool
597 compare_exchange_strong(__int_type& __i1, __int_type __i2,
598 memory_order __m1, memory_order __m2)
noexcept
600 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
602 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0,
603 int(__m1),
int(__m2));
606 _GLIBCXX_ALWAYS_INLINE
bool
607 compare_exchange_strong(__int_type& __i1, __int_type __i2,
609 memory_order __m2)
volatile noexcept
611 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
613 return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0,
614 int(__m1),
int(__m2));
617 _GLIBCXX_ALWAYS_INLINE
bool
618 compare_exchange_strong(__int_type& __i1, __int_type __i2,
619 memory_order __m = memory_order_seq_cst)
noexcept
621 return compare_exchange_strong(__i1, __i2, __m,
622 __cmpexch_failure_order(__m));
625 _GLIBCXX_ALWAYS_INLINE
bool
626 compare_exchange_strong(__int_type& __i1, __int_type __i2,
627 memory_order __m = memory_order_seq_cst)
volatile noexcept
629 return compare_exchange_strong(__i1, __i2, __m,
630 __cmpexch_failure_order(__m));
633#if __glibcxx_atomic_wait
634 _GLIBCXX_ALWAYS_INLINE
void
635 wait(__int_type __old,
636 memory_order __m = memory_order_seq_cst)
const noexcept
638 std::__atomic_wait_address_v(&_M_i, __old,
639 [__m,
this] {
return this->load(__m); });
644 _GLIBCXX_ALWAYS_INLINE
void
645 notify_one() noexcept
646 { std::__atomic_notify_address(&_M_i,
false); }
650 _GLIBCXX_ALWAYS_INLINE
void
651 notify_all() noexcept
652 { std::__atomic_notify_address(&_M_i,
true); }
657 _GLIBCXX_ALWAYS_INLINE __int_type
658 fetch_add(__int_type __i,
659 memory_order __m = memory_order_seq_cst)
noexcept
660 {
return __atomic_fetch_add(&_M_i, __i,
int(__m)); }
662 _GLIBCXX_ALWAYS_INLINE __int_type
663 fetch_add(__int_type __i,
664 memory_order __m = memory_order_seq_cst)
volatile noexcept
665 {
return __atomic_fetch_add(&_M_i, __i,
int(__m)); }
667 _GLIBCXX_ALWAYS_INLINE __int_type
668 fetch_sub(__int_type __i,
669 memory_order __m = memory_order_seq_cst)
noexcept
670 {
return __atomic_fetch_sub(&_M_i, __i,
int(__m)); }
672 _GLIBCXX_ALWAYS_INLINE __int_type
673 fetch_sub(__int_type __i,
674 memory_order __m = memory_order_seq_cst)
volatile noexcept
675 {
return __atomic_fetch_sub(&_M_i, __i,
int(__m)); }
677 _GLIBCXX_ALWAYS_INLINE __int_type
678 fetch_and(__int_type __i,
679 memory_order __m = memory_order_seq_cst)
noexcept
680 {
return __atomic_fetch_and(&_M_i, __i,
int(__m)); }
682 _GLIBCXX_ALWAYS_INLINE __int_type
683 fetch_and(__int_type __i,
684 memory_order __m = memory_order_seq_cst)
volatile noexcept
685 {
return __atomic_fetch_and(&_M_i, __i,
int(__m)); }
687 _GLIBCXX_ALWAYS_INLINE __int_type
688 fetch_or(__int_type __i,
689 memory_order __m = memory_order_seq_cst)
noexcept
690 {
return __atomic_fetch_or(&_M_i, __i,
int(__m)); }
692 _GLIBCXX_ALWAYS_INLINE __int_type
693 fetch_or(__int_type __i,
694 memory_order __m = memory_order_seq_cst)
volatile noexcept
695 {
return __atomic_fetch_or(&_M_i, __i,
int(__m)); }
697 _GLIBCXX_ALWAYS_INLINE __int_type
698 fetch_xor(__int_type __i,
699 memory_order __m = memory_order_seq_cst)
noexcept
700 {
return __atomic_fetch_xor(&_M_i, __i,
int(__m)); }
702 _GLIBCXX_ALWAYS_INLINE __int_type
703 fetch_xor(__int_type __i,
704 memory_order __m = memory_order_seq_cst)
volatile noexcept
705 {
return __atomic_fetch_xor(&_M_i, __i,
int(__m)); }
707#if __glibcxx_atomic_min_max
708 _GLIBCXX_ALWAYS_INLINE __int_type
709 fetch_min(__int_type __i,
710 memory_order __m = memory_order_seq_cst)
noexcept
711 {
return __atomic_impl::__fetch_min(&_M_i, __i, __m); }
713 _GLIBCXX_ALWAYS_INLINE __int_type
714 fetch_min(__int_type __i,
715 memory_order __m = memory_order_seq_cst)
volatile noexcept
716 {
return __atomic_impl::__fetch_min(&_M_i, __i, __m); }
718 _GLIBCXX_ALWAYS_INLINE __int_type
719 fetch_max(__int_type __i,
720 memory_order __m = memory_order_seq_cst)
noexcept
721 {
return __atomic_impl::__fetch_max(&_M_i, __i, __m); }
723 _GLIBCXX_ALWAYS_INLINE __int_type
724 fetch_max(__int_type __i,
725 memory_order __m = memory_order_seq_cst)
volatile noexcept
726 {
return __atomic_impl::__fetch_max(&_M_i, __i, __m); }
732 template<
typename _PTp>
733 struct __atomic_base<_PTp*>
736 typedef _PTp* __pointer_type;
738 __pointer_type _M_p _GLIBCXX20_INIT(
nullptr);
740 static constexpr ptrdiff_t
741 _S_type_size(ptrdiff_t __d)
742 {
return __d *
sizeof(_PTp); }
745 __atomic_base() noexcept = default;
746 ~__atomic_base() noexcept = default;
747 __atomic_base(const __atomic_base&) = delete;
748 __atomic_base& operator=(const __atomic_base&) = delete;
749 __atomic_base& operator=(const __atomic_base&) volatile = delete;
752 constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { }
754 operator __pointer_type() const noexcept
757 operator __pointer_type() const volatile noexcept
761 operator=(__pointer_type __p)
noexcept
768 operator=(__pointer_type __p)
volatile noexcept
775 operator++(
int)
noexcept
776 {
return fetch_add(1); }
779 operator++(
int)
volatile noexcept
780 {
return fetch_add(1); }
783 operator--(
int)
noexcept
784 {
return fetch_sub(1); }
787 operator--(
int)
volatile noexcept
788 {
return fetch_sub(1); }
791 operator++() noexcept
792 {
return __atomic_add_fetch(&_M_p, _S_type_size(1),
793 int(memory_order_seq_cst)); }
796 operator++() volatile noexcept
797 {
return __atomic_add_fetch(&_M_p, _S_type_size(1),
798 int(memory_order_seq_cst)); }
801 operator--() noexcept
802 {
return __atomic_sub_fetch(&_M_p, _S_type_size(1),
803 int(memory_order_seq_cst)); }
806 operator--() volatile noexcept
807 {
return __atomic_sub_fetch(&_M_p, _S_type_size(1),
808 int(memory_order_seq_cst)); }
811 operator+=(ptrdiff_t __d)
noexcept
812 {
return __atomic_add_fetch(&_M_p, _S_type_size(__d),
813 int(memory_order_seq_cst)); }
816 operator+=(ptrdiff_t __d)
volatile noexcept
817 {
return __atomic_add_fetch(&_M_p, _S_type_size(__d),
818 int(memory_order_seq_cst)); }
821 operator-=(ptrdiff_t __d)
noexcept
822 {
return __atomic_sub_fetch(&_M_p, _S_type_size(__d),
823 int(memory_order_seq_cst)); }
826 operator-=(ptrdiff_t __d)
volatile noexcept
827 {
return __atomic_sub_fetch(&_M_p, _S_type_size(__d),
828 int(memory_order_seq_cst)); }
831 is_lock_free() const noexcept
834 return __atomic_is_lock_free(
sizeof(_M_p),
835 reinterpret_cast<void *
>(-__alignof(_M_p)));
839 is_lock_free() const volatile noexcept
842 return __atomic_is_lock_free(
sizeof(_M_p),
843 reinterpret_cast<void *
>(-__alignof(_M_p)));
846#pragma GCC diagnostic push
847#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
848 _GLIBCXX_ALWAYS_INLINE
void
849 store(__pointer_type __p,
853 = __m & __memory_order_mask;
855 __glibcxx_assert(__b != memory_order_acquire);
856 __glibcxx_assert(__b != memory_order_acq_rel);
857 __glibcxx_assert(__b != memory_order_consume);
859 __atomic_store_n(&_M_p, __p,
int(__m));
862 _GLIBCXX_ALWAYS_INLINE
void
863 store(__pointer_type __p,
864 memory_order __m = memory_order_seq_cst)
volatile noexcept
867 = __m & __memory_order_mask;
868 __glibcxx_assert(__b != memory_order_acquire);
869 __glibcxx_assert(__b != memory_order_acq_rel);
870 __glibcxx_assert(__b != memory_order_consume);
872 __atomic_store_n(&_M_p, __p,
int(__m));
874#pragma GCC diagnostic pop
876 _GLIBCXX_ALWAYS_INLINE __pointer_type
877 load(
memory_order __m = memory_order_seq_cst)
const noexcept
880 = __m & __memory_order_mask;
881 __glibcxx_assert(__b != memory_order_release);
882 __glibcxx_assert(__b != memory_order_acq_rel);
884 return __atomic_load_n(&_M_p,
int(__m));
887 _GLIBCXX_ALWAYS_INLINE __pointer_type
888 load(
memory_order __m = memory_order_seq_cst)
const volatile noexcept
891 = __m & __memory_order_mask;
892 __glibcxx_assert(__b != memory_order_release);
893 __glibcxx_assert(__b != memory_order_acq_rel);
895 return __atomic_load_n(&_M_p,
int(__m));
898 _GLIBCXX_ALWAYS_INLINE __pointer_type
899 exchange(__pointer_type __p,
902 return __atomic_exchange_n(&_M_p, __p,
int(__m));
906 _GLIBCXX_ALWAYS_INLINE __pointer_type
907 exchange(__pointer_type __p,
908 memory_order __m = memory_order_seq_cst)
volatile noexcept
910 return __atomic_exchange_n(&_M_p, __p,
int(__m));
913 _GLIBCXX_ALWAYS_INLINE
bool
914 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
918 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
920 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1,
921 int(__m1),
int(__m2));
924 _GLIBCXX_ALWAYS_INLINE
bool
925 compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2,
929 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
931 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 1,
932 int(__m1),
int(__m2));
935 _GLIBCXX_ALWAYS_INLINE
bool
936 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
940 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
942 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0,
943 int(__m1),
int(__m2));
946 _GLIBCXX_ALWAYS_INLINE
bool
947 compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2,
951 __glibcxx_assert(__is_valid_cmpexch_failure_order(__m2));
953 return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0,
954 int(__m1),
int(__m2));
957#if __glibcxx_atomic_wait
958 _GLIBCXX_ALWAYS_INLINE
void
959 wait(__pointer_type __old,
962 std::__atomic_wait_address_v(&_M_p, __old,
964 {
return this->load(__m); });
969 _GLIBCXX_ALWAYS_INLINE
void
970 notify_one() const noexcept
971 { std::__atomic_notify_address(&_M_p,
false); }
975 _GLIBCXX_ALWAYS_INLINE
void
976 notify_all() const noexcept
977 { std::__atomic_notify_address(&_M_p,
true); }
982 _GLIBCXX_ALWAYS_INLINE __pointer_type
983 fetch_add(ptrdiff_t __d,
985 {
return __atomic_fetch_add(&_M_p, _S_type_size(__d),
int(__m)); }
987 _GLIBCXX_ALWAYS_INLINE __pointer_type
988 fetch_add(ptrdiff_t __d,
989 memory_order __m = memory_order_seq_cst)
volatile noexcept
990 {
return __atomic_fetch_add(&_M_p, _S_type_size(__d),
int(__m)); }
992 _GLIBCXX_ALWAYS_INLINE __pointer_type
993 fetch_sub(ptrdiff_t __d,
995 {
return __atomic_fetch_sub(&_M_p, _S_type_size(__d),
int(__m)); }
997 _GLIBCXX_ALWAYS_INLINE __pointer_type
998 fetch_sub(ptrdiff_t __d,
999 memory_order __m = memory_order_seq_cst)
volatile noexcept
1000 {
return __atomic_fetch_sub(&_M_p, _S_type_size(__d),
int(__m)); }
1002#if __glibcxx_atomic_min_max
1003 _GLIBCXX_ALWAYS_INLINE __pointer_type
1004 fetch_min(__pointer_type __p,
1006 {
return __atomic_impl::__fetch_min(&_M_p, __p, __m); }
1008 _GLIBCXX_ALWAYS_INLINE __pointer_type
1009 fetch_min(__pointer_type __p,
1010 memory_order __m = memory_order_seq_cst)
volatile noexcept
1011 {
return __atomic_impl::__fetch_min(&_M_p, __p, __m); }
1013 _GLIBCXX_ALWAYS_INLINE __pointer_type
1014 fetch_max(__pointer_type __p,
1016 {
return __atomic_impl::__fetch_max(&_M_p, __p, __m); }
1018 _GLIBCXX_ALWAYS_INLINE __pointer_type
1019 fetch_max(__pointer_type __p,
1020 memory_order __m = memory_order_seq_cst)
volatile noexcept
1021 {
return __atomic_impl::__fetch_max(&_M_p, __p, __m); }
1025 namespace __atomic_impl
1029 template<
typename _Tp>
1031 __maybe_has_padding()
1033#if ! __has_builtin(__builtin_clear_padding)
1035#elif __has_builtin(__has_unique_object_representations)
1036 return !__has_unique_object_representations(_Tp)
1037 && !is_same<_Tp, float>::value && !is_same<_Tp, double>::value;
1043#pragma GCC diagnostic push
1044#pragma GCC diagnostic ignored "-Wc++17-extensions"
1046 template<
typename _Tp>
1047 _GLIBCXX_ALWAYS_INLINE _GLIBCXX14_CONSTEXPR _Tp*
1048 __clear_padding(_Tp& __val)
noexcept
1051#if __has_builtin(__builtin_clear_padding)
1052 if constexpr (__atomic_impl::__maybe_has_padding<_Tp>())
1053 __builtin_clear_padding(__ptr);
1058 template<
bool _AtomicRef = false,
typename _Tp>
1059 _GLIBCXX_ALWAYS_INLINE
bool
1060 __compare_exchange(_Tp& __val, _Val<_Tp>& __e, _Val<_Tp>& __i,
1062 memory_order __s, memory_order __f)
noexcept
1064 __glibcxx_assert(__is_valid_cmpexch_failure_order(__f));
1066 using _Vp = _Val<_Tp>;
1069 if constexpr (!__atomic_impl::__maybe_has_padding<_Vp>())
1073 int(__s),
int(__f));
1075 else if constexpr (!_AtomicRef)
1078 _Vp*
const __pi = __atomic_impl::__clear_padding(__i);
1082 _Vp*
const __pexp = __atomic_impl::__clear_padding(__exp);
1086 if (__atomic_compare_exchange(__pval, __pexp, __pi,
1087 __is_weak,
int(__s),
int(__f)))
1096 _Vp*
const __pi = __atomic_impl::__clear_padding(__i);
1102 _Vp*
const __pexp = __atomic_impl::__clear_padding(__exp);
1119 if (__atomic_compare_exchange(__pval, __pexp, __pi,
1120 __is_weak,
int(__s),
int(__f)))
1127 if (__builtin_memcmp(__atomic_impl::__clear_padding(__orig),
1128 __atomic_impl::__clear_padding(__curr),
1139#pragma GCC diagnostic pop
1142#if __cplusplus > 201703L
1144 namespace __atomic_impl
1147 template<
typename _Tp>
1148 using _Diff = __conditional_t<is_pointer_v<_Tp>, ptrdiff_t, _Val<_Tp>>;
1150 template<
size_t _Size,
size_t _Align>
1151 _GLIBCXX_ALWAYS_INLINE
bool
1152 is_lock_free() noexcept
1155 return __atomic_is_lock_free(_Size,
reinterpret_cast<void *
>(-_Align));
1158 template<
typename _Tp>
1159 _GLIBCXX_ALWAYS_INLINE
void
1160 store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m)
noexcept
1162 __atomic_store(__ptr, __atomic_impl::__clear_padding(__t),
int(__m));
1165 template<
typename _Tp>
1166 _GLIBCXX_ALWAYS_INLINE _Val<_Tp>
1167 load(
const _Tp* __ptr, memory_order __m)
noexcept
1169 alignas(_Tp)
unsigned char __buf[
sizeof(_Tp)];
1170 auto* __dest =
reinterpret_cast<_Val<_Tp>*
>(__buf);
1171 __atomic_load(__ptr, __dest,
int(__m));
1175 template<
typename _Tp>
1176 _GLIBCXX_ALWAYS_INLINE _Val<_Tp>
1177 exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m)
noexcept
1179 alignas(_Tp)
unsigned char __buf[
sizeof(_Tp)];
1180 auto* __dest =
reinterpret_cast<_Val<_Tp>*
>(__buf);
1181 __atomic_exchange(__ptr, __atomic_impl::__clear_padding(__desired),
1186 template<
bool _AtomicRef = false,
typename _Tp>
1187 _GLIBCXX_ALWAYS_INLINE
bool
1188 compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected,
1189 _Val<_Tp> __desired, memory_order __success,
1190 memory_order __failure)
noexcept
1192 return __atomic_impl::__compare_exchange<_AtomicRef>(
1193 *__ptr, __expected, __desired,
true, __success, __failure);
1196 template<
bool _AtomicRef = false,
typename _Tp>
1197 _GLIBCXX_ALWAYS_INLINE
bool
1198 compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected,
1199 _Val<_Tp> __desired, memory_order __success,
1200 memory_order __failure)
noexcept
1202 return __atomic_impl::__compare_exchange<_AtomicRef>(
1203 *__ptr, __expected, __desired,
false, __success, __failure);
1206#if __glibcxx_atomic_wait
1207 template<
typename _Tp>
1208 _GLIBCXX_ALWAYS_INLINE
void
1209 wait(
const _Tp* __ptr, _Val<_Tp> __old,
1210 memory_order __m = memory_order_seq_cst)
noexcept
1212 std::__atomic_wait_address_v(__ptr, __old,
1213 [__ptr, __m]() {
return __atomic_impl::load(__ptr, __m); });
1218 template<
typename _Tp>
1219 _GLIBCXX_ALWAYS_INLINE
void
1220 notify_one(
const _Tp* __ptr)
noexcept
1221 { std::__atomic_notify_address(__ptr,
false); }
1225 template<
typename _Tp>
1226 _GLIBCXX_ALWAYS_INLINE
void
1227 notify_all(
const _Tp* __ptr)
noexcept
1228 { std::__atomic_notify_address(__ptr,
true); }
1233 template<
typename _Tp>
1234 _GLIBCXX_ALWAYS_INLINE _Tp
1235 fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m)
noexcept
1236 {
return __atomic_fetch_add(__ptr, __i,
int(__m)); }
1238 template<
typename _Tp>
1239 _GLIBCXX_ALWAYS_INLINE _Tp
1240 fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m)
noexcept
1241 {
return __atomic_fetch_sub(__ptr, __i,
int(__m)); }
1243 template<
typename _Tp>
1244 _GLIBCXX_ALWAYS_INLINE _Tp
1245 fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1246 {
return __atomic_fetch_and(__ptr, __i,
int(__m)); }
1248 template<
typename _Tp>
1249 _GLIBCXX_ALWAYS_INLINE _Tp
1250 fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1251 {
return __atomic_fetch_or(__ptr, __i,
int(__m)); }
1253 template<
typename _Tp>
1254 _GLIBCXX_ALWAYS_INLINE _Tp
1255 fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1256 {
return __atomic_fetch_xor(__ptr, __i,
int(__m)); }
1258 template<
typename _Tp>
1259 _GLIBCXX_ALWAYS_INLINE _Tp
1260 __add_fetch(_Tp* __ptr, _Diff<_Tp> __i)
noexcept
1261 {
return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1263 template<
typename _Tp>
1264 _GLIBCXX_ALWAYS_INLINE _Tp
1265 __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i)
noexcept
1266 {
return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1268 template<
typename _Tp>
1269 _GLIBCXX_ALWAYS_INLINE _Tp
1270 __and_fetch(_Tp* __ptr, _Val<_Tp> __i)
noexcept
1271 {
return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1273 template<
typename _Tp>
1274 _GLIBCXX_ALWAYS_INLINE _Tp
1275 __or_fetch(_Tp* __ptr, _Val<_Tp> __i)
noexcept
1276 {
return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1278 template<
typename _Tp>
1279 _GLIBCXX_ALWAYS_INLINE _Tp
1280 __xor_fetch(_Tp* __ptr, _Val<_Tp> __i)
noexcept
1281 {
return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); }
1283 template<
typename _Tp>
1284 concept __atomic_fetch_addable
1285 =
requires (_Tp __t) { __atomic_fetch_add(&__t, __t, 0); };
1287 template<
typename _Tp>
1289 __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1291 if constexpr (__atomic_fetch_addable<_Tp>)
1292 return __atomic_fetch_add(__ptr, __i,
int(__m));
1295 _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
1296 _Val<_Tp> __newval = __oldval + __i;
1297 while (!compare_exchange_weak (__ptr, __oldval, __newval, __m,
1298 memory_order_relaxed))
1299 __newval = __oldval + __i;
1304 template<
typename _Tp>
1305 concept __atomic_fetch_subtractable
1306 =
requires (_Tp __t) { __atomic_fetch_sub(&__t, __t, 0); };
1308 template<
typename _Tp>
1310 __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1312 if constexpr (__atomic_fetch_subtractable<_Tp>)
1313 return __atomic_fetch_sub(__ptr, __i,
int(__m));
1316 _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
1317 _Val<_Tp> __newval = __oldval - __i;
1318 while (!compare_exchange_weak (__ptr, __oldval, __newval, __m,
1319 memory_order_relaxed))
1320 __newval = __oldval - __i;
1325 template<
typename _Tp>
1326 concept __atomic_add_fetchable
1327 =
requires (_Tp __t) { __atomic_add_fetch(&__t, __t, 0); };
1329 template<
typename _Tp>
1331 __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i)
noexcept
1333 if constexpr (__atomic_add_fetchable<_Tp>)
1334 return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST);
1337 _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
1338 _Val<_Tp> __newval = __oldval + __i;
1339 while (!compare_exchange_weak (__ptr, __oldval, __newval,
1340 memory_order_seq_cst,
1341 memory_order_relaxed))
1342 __newval = __oldval + __i;
1347 template<
typename _Tp>
1348 concept __atomic_sub_fetchable
1349 =
requires (_Tp __t) { __atomic_sub_fetch(&__t, __t, 0); };
1351 template<
typename _Tp>
1353 __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i)
noexcept
1355 if constexpr (__atomic_sub_fetchable<_Tp>)
1356 return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST);
1359 _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
1360 _Val<_Tp> __newval = __oldval - __i;
1361 while (!compare_exchange_weak (__ptr, __oldval, __newval,
1362 memory_order_seq_cst,
1363 memory_order_relaxed))
1364 __newval = __oldval - __i;
1369#if __glibcxx_atomic_min_max
1370 template<
typename _Tp>
1371 concept __atomic_fetch_minmaxable
1372 =
requires (_Tp __t) {
1373 __atomic_fetch_min(&__t, __t, 0);
1374 __atomic_fetch_max(&__t, __t, 0);
1377 template<
typename _Tp>
1379 __fetch_min(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1381 if constexpr (__atomic_fetch_minmaxable<_Tp>)
1382 return __atomic_fetch_min(__ptr, __i,
int(__m));
1385 _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
1386 _Val<_Tp> __newval = __oldval < __i ? __oldval : __i;
1387 while (!compare_exchange_weak (__ptr, __oldval, __newval, __m,
1388 memory_order_relaxed))
1389 __newval = __oldval < __i ? __oldval : __i;
1394 template<
typename _Tp>
1396 __fetch_max(_Tp* __ptr, _Val<_Tp> __i, memory_order __m)
noexcept
1398 if constexpr (__atomic_fetch_minmaxable<_Tp>)
1399 return __atomic_fetch_max(__ptr, __i,
int(__m));
1402 _Val<_Tp> __oldval = load (__ptr, memory_order_relaxed);
1403 _Val<_Tp> __newval = __oldval > __i ? __oldval : __i;
1404 while (!compare_exchange_weak (__ptr, __oldval, __newval, __m,
1405 memory_order_relaxed))
1406 __newval = __oldval > __i ? __oldval : __i;
1414 template<
typename _Fp>
1415 struct __atomic_float
1417 static_assert(is_floating_point_v<_Fp>);
1419 static constexpr size_t _S_alignment = __alignof__(_Fp);
1422 using value_type = _Fp;
1423 using difference_type = value_type;
1425 static constexpr bool is_always_lock_free
1426 = __atomic_always_lock_free(
sizeof(_Fp), 0);
1428 __atomic_float() =
default;
1431 __atomic_float(_Fp __t) : _M_fp(__t)
1433 if (!std::__is_constant_evaluated())
1434 __atomic_impl::__clear_padding(_M_fp);
1437 __atomic_float(
const __atomic_float&) =
delete;
1438 __atomic_float& operator=(
const __atomic_float&) =
delete;
1439 __atomic_float& operator=(
const __atomic_float&)
volatile =
delete;
1442 operator=(_Fp __t)
volatile noexcept
1449 operator=(_Fp __t)
noexcept
1456 is_lock_free() const volatile noexcept
1457 {
return __atomic_impl::is_lock_free<sizeof(_Fp), _S_alignment>(); }
1460 is_lock_free() const noexcept
1461 {
return __atomic_impl::is_lock_free<sizeof(_Fp), _S_alignment>(); }
1464 store(_Fp __t, memory_order __m = memory_order_seq_cst)
volatile noexcept
1465 { __atomic_impl::store(&_M_fp, __t, __m); }
1468 store(_Fp __t, memory_order __m = memory_order_seq_cst)
noexcept
1469 { __atomic_impl::store(&_M_fp, __t, __m); }
1472 load(memory_order __m = memory_order_seq_cst)
const volatile noexcept
1473 {
return __atomic_impl::load(&_M_fp, __m); }
1476 load(memory_order __m = memory_order_seq_cst)
const noexcept
1477 {
return __atomic_impl::load(&_M_fp, __m); }
1479 operator _Fp() const volatile noexcept {
return this->load(); }
1480 operator _Fp() const noexcept {
return this->load(); }
1483 exchange(_Fp __desired,
1484 memory_order __m = memory_order_seq_cst)
volatile noexcept
1485 {
return __atomic_impl::exchange(&_M_fp, __desired, __m); }
1488 exchange(_Fp __desired,
1489 memory_order __m = memory_order_seq_cst)
noexcept
1490 {
return __atomic_impl::exchange(&_M_fp, __desired, __m); }
1493 compare_exchange_weak(_Fp& __expected, _Fp __desired,
1494 memory_order __success,
1495 memory_order __failure)
noexcept
1497 return __atomic_impl::compare_exchange_weak(&_M_fp,
1498 __expected, __desired,
1499 __success, __failure);
1503 compare_exchange_weak(_Fp& __expected, _Fp __desired,
1504 memory_order __success,
1505 memory_order __failure)
volatile noexcept
1507 return __atomic_impl::compare_exchange_weak(&_M_fp,
1508 __expected, __desired,
1509 __success, __failure);
1513 compare_exchange_strong(_Fp& __expected, _Fp __desired,
1514 memory_order __success,
1515 memory_order __failure)
noexcept
1517 return __atomic_impl::compare_exchange_strong(&_M_fp,
1518 __expected, __desired,
1519 __success, __failure);
1523 compare_exchange_strong(_Fp& __expected, _Fp __desired,
1524 memory_order __success,
1525 memory_order __failure)
volatile noexcept
1527 return __atomic_impl::compare_exchange_strong(&_M_fp,
1528 __expected, __desired,
1529 __success, __failure);
1533 compare_exchange_weak(_Fp& __expected, _Fp __desired,
1534 memory_order __order = memory_order_seq_cst)
1537 return compare_exchange_weak(__expected, __desired, __order,
1538 __cmpexch_failure_order(__order));
1542 compare_exchange_weak(_Fp& __expected, _Fp __desired,
1543 memory_order __order = memory_order_seq_cst)
1546 return compare_exchange_weak(__expected, __desired, __order,
1547 __cmpexch_failure_order(__order));
1551 compare_exchange_strong(_Fp& __expected, _Fp __desired,
1552 memory_order __order = memory_order_seq_cst)
1555 return compare_exchange_strong(__expected, __desired, __order,
1556 __cmpexch_failure_order(__order));
1560 compare_exchange_strong(_Fp& __expected, _Fp __desired,
1561 memory_order __order = memory_order_seq_cst)
1564 return compare_exchange_strong(__expected, __desired, __order,
1565 __cmpexch_failure_order(__order));
1568#if __glibcxx_atomic_wait
1569 _GLIBCXX_ALWAYS_INLINE
void
1570 wait(_Fp __old, memory_order __m = memory_order_seq_cst)
const noexcept
1571 { __atomic_impl::wait(&_M_fp, __old, __m); }
1575 _GLIBCXX_ALWAYS_INLINE
void
1576 notify_one() const noexcept
1577 { __atomic_impl::notify_one(&_M_fp); }
1581 _GLIBCXX_ALWAYS_INLINE
void
1582 notify_all() const noexcept
1583 { __atomic_impl::notify_all(&_M_fp); }
1589 fetch_add(value_type __i,
1590 memory_order __m = memory_order_seq_cst)
noexcept
1591 {
return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); }
1594 fetch_add(value_type __i,
1595 memory_order __m = memory_order_seq_cst)
volatile noexcept
1596 {
return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); }
1599 fetch_sub(value_type __i,
1600 memory_order __m = memory_order_seq_cst)
noexcept
1601 {
return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); }
1604 fetch_sub(value_type __i,
1605 memory_order __m = memory_order_seq_cst)
volatile noexcept
1606 {
return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); }
1608#if __glibcxx_atomic_min_max
1610 fetch_min(value_type __i,
1611 memory_order __m = memory_order_seq_cst)
noexcept
1612 {
return __atomic_impl::__fetch_min(&_M_fp, __i, __m); }
1615 fetch_min(value_type __i,
1616 memory_order __m = memory_order_seq_cst)
volatile noexcept
1617 {
return __atomic_impl::__fetch_min(&_M_fp, __i, __m); }
1620 fetch_max(value_type __i,
1621 memory_order __m = memory_order_seq_cst)
noexcept
1622 {
return __atomic_impl::__fetch_max(&_M_fp, __i, __m); }
1625 fetch_max(value_type __i,
1626 memory_order __m = memory_order_seq_cst)
volatile noexcept
1627 {
return __atomic_impl::__fetch_max(&_M_fp, __i, __m); }
1631 operator+=(value_type __i)
noexcept
1632 {
return __atomic_impl::__add_fetch_flt(&_M_fp, __i); }
1635 operator+=(value_type __i)
volatile noexcept
1636 {
return __atomic_impl::__add_fetch_flt(&_M_fp, __i); }
1639 operator-=(value_type __i)
noexcept
1640 {
return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); }
1643 operator-=(value_type __i)
volatile noexcept
1644 {
return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); }
1647 alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0);
1649#undef _GLIBCXX20_INIT
1659 template<
typename _Tp>
1660 struct __atomic_ref_base;
1662 template<
typename _Tp>
1663 struct __atomic_ref_base<const _Tp>
1666 using _Vt = remove_cv_t<_Tp>;
1667 using _Address_return_t = __conditional_t<is_volatile_v<_Tp>,
1668 const volatile void*,
const void*>;
1670 static consteval bool
1671 _S_is_always_lock_free()
1673 if constexpr (is_pointer_v<_Vt>)
1674 return ATOMIC_POINTER_LOCK_FREE == 2;
1676 return __atomic_always_lock_free(
sizeof(_Vt), 0);
1679 static consteval int
1680 _S_required_alignment()
1682 if constexpr (is_floating_point_v<_Vt> || is_pointer_v<_Vt>)
1683 return __alignof__(_Vt);
1684 else if constexpr ((
sizeof(_Vt) & (
sizeof(_Vt) - 1)) ||
sizeof(_Vt) > 16)
1685 return alignof(_Vt);
1689 return (
sizeof(_Vt) >
alignof(_Vt)) ?
sizeof(_Vt) : alignof(_Vt);
1693 using value_type = _Vt;
1694 static_assert(is_trivially_copyable_v<value_type>);
1696 static constexpr bool is_always_lock_free = _S_is_always_lock_free();
1697 static_assert(is_always_lock_free || !is_volatile_v<_Tp>,
1698 "atomic operations on volatile T must be lock-free");
1700 static constexpr size_t required_alignment = _S_required_alignment();
1702 __atomic_ref_base() =
delete;
1703 __atomic_ref_base& operator=(
const __atomic_ref_base&) =
delete;
1706 __atomic_ref_base(
const _Tp* __ptr) noexcept
1707 : _M_ptr(
const_cast<_Tp*
>(__ptr))
1710 __atomic_ref_base(
const __atomic_ref_base&)
noexcept =
default;
1712 operator value_type() const noexcept {
return this->load(); }
1715 is_lock_free() const noexcept
1716 {
return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>(); }
1719 load(memory_order __m = memory_order_seq_cst)
const noexcept
1720 {
return __atomic_impl::load(_M_ptr, __m); }
1722#if __glibcxx_atomic_wait
1723 _GLIBCXX_ALWAYS_INLINE
void
1724 wait(value_type __old, memory_order __m = memory_order_seq_cst)
const noexcept
1727 static_assert(!is_volatile_v<_Tp>,
1728 "atomic waits on volatile are not supported");
1729 __atomic_impl::wait(_M_ptr, __old, __m);
1733#if __glibcxx_atomic_ref >= 202603L
1734 _GLIBCXX_ALWAYS_INLINE
constexpr _Address_return_t
1735 address() const noexcept
1743 template<
typename _Tp>
1744 struct __atomic_ref_base
1745 : __atomic_ref_base<const _Tp>
1747 using _Address_return_t = __conditional_t<is_volatile_v<_Tp>,
1748 volatile void*,
void*>;
1751 using value_type =
typename __atomic_ref_base<const _Tp>::value_type;
1754 __atomic_ref_base(_Tp* __ptr) noexcept
1755 : __atomic_ref_base<const _Tp>(__ptr)
1759 operator=(value_type __t)
const noexcept
1766 store(value_type __t, memory_order __m = memory_order_seq_cst)
const noexcept
1767 { __atomic_impl::store(this->_M_ptr, __t, __m); }
1770 exchange(value_type __desired, memory_order __m = memory_order_seq_cst)
1772 {
return __atomic_impl::exchange(this->_M_ptr, __desired, __m); }
1775 compare_exchange_weak(value_type& __expected, value_type __desired,
1776 memory_order __success,
1777 memory_order __failure)
const noexcept
1779 return __atomic_impl::compare_exchange_weak<true>(
1780 this->_M_ptr, __expected, __desired, __success, __failure);
1784 compare_exchange_strong(value_type& __expected, value_type __desired,
1785 memory_order __success,
1786 memory_order __failure)
const noexcept
1788 return __atomic_impl::compare_exchange_strong<true>(
1789 this->_M_ptr, __expected, __desired, __success, __failure);
1793 compare_exchange_weak(value_type& __expected, value_type __desired,
1794 memory_order __order = memory_order_seq_cst)
1797 return compare_exchange_weak(__expected, __desired, __order,
1798 __cmpexch_failure_order(__order));
1802 compare_exchange_strong(value_type& __expected, value_type __desired,
1803 memory_order __order = memory_order_seq_cst)
1806 return compare_exchange_strong(__expected, __desired, __order,
1807 __cmpexch_failure_order(__order));
1810#if __glibcxx_atomic_wait
1811 _GLIBCXX_ALWAYS_INLINE
void
1812 notify_one() const noexcept
1815 static_assert(!is_volatile_v<_Tp>,
1816 "atomic waits on volatile are not supported");
1817 __atomic_impl::notify_one(this->_M_ptr);
1820 _GLIBCXX_ALWAYS_INLINE
void
1821 notify_all() const noexcept
1824 static_assert(!is_volatile_v<_Tp>,
1825 "atomic waits on volatile are not supported");
1826 __atomic_impl::notify_all(this->_M_ptr);
1830#if __glibcxx_atomic_ref >= 202603L
1831 _GLIBCXX_ALWAYS_INLINE
constexpr _Address_return_t
1832 address() const noexcept
1833 {
return this->_M_ptr; }
1837 template<
typename _Tp,
1838 bool = is_integral_v<_Tp> && !is_same_v<remove_cv_t<_Tp>,
bool>,
1839 bool = is_floating_point_v<_Tp>,
1840 bool = is_pointer_v<_Tp>>
1841 struct __atomic_ref;
1844 template<
typename _Tp>
1845 struct __atomic_ref<_Tp, false, false, false>
1846 : __atomic_ref_base<_Tp>
1848 using __atomic_ref_base<_Tp>::__atomic_ref_base;
1849 using __atomic_ref_base<_Tp>::operator=;
1852 template<
typename _Tp>
1853 struct __atomic_ref<const _Tp, false, false, false>
1854 : __atomic_ref_base<const _Tp>
1856 using __atomic_ref_base<
const _Tp>::__atomic_ref_base;
1860 template<
typename _Tp>
1861 struct __atomic_ref<_Tp, true, false, false>
1862 : __atomic_ref_base<_Tp>
1864 using value_type =
typename __atomic_ref_base<_Tp>::value_type;
1865 using difference_type = value_type;
1867 using __atomic_ref_base<_Tp>::__atomic_ref_base;
1868 using __atomic_ref_base<_Tp>::operator=;
1871 fetch_add(value_type __i,
1872 memory_order __m = memory_order_seq_cst)
const noexcept
1873 {
return __atomic_impl::fetch_add(this->_M_ptr, __i, __m); }
1876 fetch_sub(value_type __i,
1877 memory_order __m = memory_order_seq_cst)
const noexcept
1878 {
return __atomic_impl::fetch_sub(this->_M_ptr, __i, __m); }
1881 fetch_and(value_type __i,
1882 memory_order __m = memory_order_seq_cst)
const noexcept
1883 {
return __atomic_impl::fetch_and(this->_M_ptr, __i, __m); }
1886 fetch_or(value_type __i,
1887 memory_order __m = memory_order_seq_cst)
const noexcept
1888 {
return __atomic_impl::fetch_or(this->_M_ptr, __i, __m); }
1891 fetch_xor(value_type __i,
1892 memory_order __m = memory_order_seq_cst)
const noexcept
1893 {
return __atomic_impl::fetch_xor(this->_M_ptr, __i, __m); }
1895#if __glibcxx_atomic_min_max
1897 fetch_min(value_type __i,
1898 memory_order __m = memory_order_seq_cst)
const noexcept
1899 {
return __atomic_impl::__fetch_min(this->_M_ptr, __i, __m); }
1902 fetch_max(value_type __i,
1903 memory_order __m = memory_order_seq_cst)
const noexcept
1904 {
return __atomic_impl::__fetch_max(this->_M_ptr, __i, __m); }
1907 _GLIBCXX_ALWAYS_INLINE value_type
1908 operator++(
int)
const noexcept
1909 {
return fetch_add(1); }
1911 _GLIBCXX_ALWAYS_INLINE value_type
1912 operator--(
int)
const noexcept
1913 {
return fetch_sub(1); }
1916 operator++() const noexcept
1917 {
return __atomic_impl::__add_fetch(this->_M_ptr, value_type(1)); }
1920 operator--() const noexcept
1921 {
return __atomic_impl::__sub_fetch(this->_M_ptr, value_type(1)); }
1924 operator+=(value_type __i)
const noexcept
1925 {
return __atomic_impl::__add_fetch(this->_M_ptr, __i); }
1928 operator-=(value_type __i)
const noexcept
1929 {
return __atomic_impl::__sub_fetch(this->_M_ptr, __i); }
1932 operator&=(value_type __i)
const noexcept
1933 {
return __atomic_impl::__and_fetch(this->_M_ptr, __i); }
1936 operator|=(value_type __i)
const noexcept
1937 {
return __atomic_impl::__or_fetch(this->_M_ptr, __i); }
1940 operator^=(value_type __i)
const noexcept
1941 {
return __atomic_impl::__xor_fetch(this->_M_ptr, __i); }
1944 template<
typename _Tp>
1945 struct __atomic_ref<const _Tp, true, false, false>
1946 : __atomic_ref_base<const _Tp>
1948 using difference_type =
typename __atomic_ref_base<const _Tp>::value_type;
1949 using __atomic_ref_base<
const _Tp>::__atomic_ref_base;
1953 template<
typename _Fp>
1954 struct __atomic_ref<_Fp, false, true, false>
1955 : __atomic_ref_base<_Fp>
1957 using value_type =
typename __atomic_ref_base<_Fp>::value_type;
1958 using difference_type = value_type;
1960 using __atomic_ref_base<_Fp>::__atomic_ref_base;
1961 using __atomic_ref_base<_Fp>::operator=;
1964 fetch_add(value_type __i,
1965 memory_order __m = memory_order_seq_cst)
const noexcept
1966 {
return __atomic_impl::__fetch_add_flt(this->_M_ptr, __i, __m); }
1969 fetch_sub(value_type __i,
1970 memory_order __m = memory_order_seq_cst)
const noexcept
1971 {
return __atomic_impl::__fetch_sub_flt(this->_M_ptr, __i, __m); }
1973#if __glibcxx_atomic_min_max
1975 fetch_min(value_type __i,
1976 memory_order __m = memory_order_seq_cst)
const noexcept
1977 {
return __atomic_impl::__fetch_min(this->_M_ptr, __i, __m); }
1980 fetch_max(value_type __i,
1981 memory_order __m = memory_order_seq_cst)
const noexcept
1982 {
return __atomic_impl::__fetch_max(this->_M_ptr, __i, __m); }
1986 operator+=(value_type __i)
const noexcept
1987 {
return __atomic_impl::__add_fetch_flt(this->_M_ptr, __i); }
1990 operator-=(value_type __i)
const noexcept
1991 {
return __atomic_impl::__sub_fetch_flt(this->_M_ptr, __i); }
1994 template<
typename _Fp>
1995 struct __atomic_ref<const _Fp, false, true, false>
1996 : __atomic_ref_base<const _Fp>
1998 using difference_type =
typename __atomic_ref_base<const _Fp>::value_type;
1999 using __atomic_ref_base<
const _Fp>::__atomic_ref_base;
2003 template<
typename _Pt>
2004 struct __atomic_ref<_Pt, false, false, true>
2005 : __atomic_ref_base<_Pt>
2007 using value_type =
typename __atomic_ref_base<_Pt>::value_type;
2008 using difference_type = ptrdiff_t;
2010 using __atomic_ref_base<_Pt>::__atomic_ref_base;
2011 using __atomic_ref_base<_Pt>::operator=;
2012 _GLIBCXX_ALWAYS_INLINE value_type
2013 fetch_add(difference_type __d,
2014 memory_order __m = memory_order_seq_cst)
const noexcept
2015 {
return __atomic_impl::fetch_add(this->_M_ptr, _S_type_size(__d), __m); }
2017 _GLIBCXX_ALWAYS_INLINE value_type
2018 fetch_sub(difference_type __d,
2019 memory_order __m = memory_order_seq_cst)
const noexcept
2020 {
return __atomic_impl::fetch_sub(this->_M_ptr, _S_type_size(__d), __m); }
2022#if __glibcxx_atomic_min_max
2023 _GLIBCXX_ALWAYS_INLINE value_type
2024 fetch_min(value_type __i,
2025 memory_order __m = memory_order_seq_cst)
const noexcept
2026 {
return __atomic_impl::__fetch_min(this->_M_ptr, __i, __m); }
2028 _GLIBCXX_ALWAYS_INLINE value_type
2029 fetch_max(value_type __i,
2030 memory_order __m = memory_order_seq_cst)
const noexcept
2031 {
return __atomic_impl::__fetch_max(this->_M_ptr, __i, __m); }
2035 operator++(
int)
const noexcept
2036 {
return fetch_add(1); }
2039 operator--(
int)
const noexcept
2040 {
return fetch_sub(1); }
2043 operator++() const noexcept
2045 return __atomic_impl::__add_fetch(this->_M_ptr, _S_type_size(1));
2049 operator--() const noexcept
2051 return __atomic_impl::__sub_fetch(this->_M_ptr, _S_type_size(1));
2055 operator+=(difference_type __d)
const noexcept
2057 return __atomic_impl::__add_fetch(this->_M_ptr, _S_type_size(__d));
2061 operator-=(difference_type __d)
const noexcept
2063 return __atomic_impl::__sub_fetch(this->_M_ptr, _S_type_size(__d));
2067 static constexpr ptrdiff_t
2068 _S_type_size(ptrdiff_t __d)
noexcept
2070 using _Et = remove_pointer_t<value_type>;
2071 static_assert(is_object_v<_Et>);
2072 return __d *
sizeof(_Et);
2076 template<
typename _Pt>
2077 struct __atomic_ref<const _Pt, false, false, true>
2078 : __atomic_ref_base<const _Pt>
2080 using difference_type = ptrdiff_t;
2081 using __atomic_ref_base<
const _Pt>::__atomic_ref_base;
2089_GLIBCXX_END_NAMESPACE_VERSION
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
_Tp kill_dependency(_Tp __y) noexcept
kill_dependency
memory_order
Enumeration for memory_order.
ISO C++ entities toplevel namespace is std.
constexpr bitset< _Nb > operator|(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.
constexpr bitset< _Nb > operator&(const bitset< _Nb > &__x, const bitset< _Nb > &__y) noexcept
Global bitwise operations on bitsets.