File indexing completed on 2026-05-03 08:13:23
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___CXX03___ATOMIC_ATOMIC_SYNC_H
0010 #define _LIBCPP___CXX03___ATOMIC_ATOMIC_SYNC_H
0011
0012 #include <__cxx03/__atomic/contention_t.h>
0013 #include <__cxx03/__atomic/cxx_atomic_impl.h>
0014 #include <__cxx03/__atomic/memory_order.h>
0015 #include <__cxx03/__atomic/to_gcc_order.h>
0016 #include <__cxx03/__chrono/duration.h>
0017 #include <__cxx03/__config>
0018 #include <__cxx03/__memory/addressof.h>
0019 #include <__cxx03/__thread/poll_with_backoff.h>
0020 #include <__cxx03/__thread/support.h>
0021 #include <__cxx03/__type_traits/conjunction.h>
0022 #include <__cxx03/__type_traits/decay.h>
0023 #include <__cxx03/__type_traits/invoke.h>
0024 #include <__cxx03/__type_traits/void_t.h>
0025 #include <__cxx03/__utility/declval.h>
0026 #include <__cxx03/cstring>
0027
0028 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0029 # pragma GCC system_header
0030 #endif
0031
0032 _LIBCPP_BEGIN_NAMESPACE_STD
0033
0034
0035
0036
0037
0038
0039
0040
0041 template <class _Tp, class = void>
0042 struct __atomic_waitable_traits {
0043 template <class _AtomicWaitable>
0044 static void __atomic_load(_AtomicWaitable&&, memory_order) = delete;
0045
0046 template <class _AtomicWaitable>
0047 static void __atomic_contention_address(_AtomicWaitable&&) = delete;
0048 };
0049
0050 template <class _Tp, class = void>
0051 struct __atomic_waitable : false_type {};
0052
0053 template <class _Tp>
0054 struct __atomic_waitable< _Tp,
0055 __void_t<decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(
0056 std::declval<const _Tp&>(), std::declval<memory_order>())),
0057 decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(
0058 std::declval<const _Tp&>()))> > : true_type {};
0059
0060 template <class _AtomicWaitable, class _Poll>
0061 struct __atomic_wait_poll_impl {
0062 const _AtomicWaitable& __a_;
0063 _Poll __poll_;
0064 memory_order __order_;
0065
0066 _LIBCPP_HIDE_FROM_ABI bool operator()() const {
0067 auto __current_val = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_load(__a_, __order_);
0068 return __poll_(__current_val);
0069 }
0070 };
0071
0072 #ifndef _LIBCPP_HAS_NO_THREADS
0073
0074 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one(void const volatile*) _NOEXCEPT;
0075 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all(void const volatile*) _NOEXCEPT;
0076 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
0077 __libcpp_atomic_monitor(void const volatile*) _NOEXCEPT;
0078 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
0079 __libcpp_atomic_wait(void const volatile*, __cxx_contention_t) _NOEXCEPT;
0080
0081 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
0082 __cxx_atomic_notify_one(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
0083 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
0084 __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
0085 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
0086 __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile*) _NOEXCEPT;
0087 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
0088 __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile*, __cxx_contention_t) _NOEXCEPT;
0089
0090 template <class _AtomicWaitable, class _Poll>
0091 struct __atomic_wait_backoff_impl {
0092 const _AtomicWaitable& __a_;
0093 _Poll __poll_;
0094 memory_order __order_;
0095
0096 using __waitable_traits = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
0097
0098 _LIBCPP_AVAILABILITY_SYNC
0099 _LIBCPP_HIDE_FROM_ABI bool
0100 __update_monitor_val_and_poll(__cxx_atomic_contention_t const volatile*, __cxx_contention_t& __monitor_val) const {
0101
0102
0103
0104
0105
0106
0107 __monitor_val = __waitable_traits::__atomic_load(__a_, __order_);
0108 return __poll_(__monitor_val);
0109 }
0110
0111 _LIBCPP_AVAILABILITY_SYNC
0112 _LIBCPP_HIDE_FROM_ABI bool
0113 __update_monitor_val_and_poll(void const volatile* __contention_address, __cxx_contention_t& __monitor_val) const {
0114
0115
0116 __monitor_val = std::__libcpp_atomic_monitor(__contention_address);
0117 auto __current_val = __waitable_traits::__atomic_load(__a_, __order_);
0118 return __poll_(__current_val);
0119 }
0120
0121 _LIBCPP_AVAILABILITY_SYNC
0122 _LIBCPP_HIDE_FROM_ABI bool operator()(chrono::nanoseconds __elapsed) const {
0123 if (__elapsed > chrono::microseconds(64)) {
0124 auto __contention_address = __waitable_traits::__atomic_contention_address(__a_);
0125 __cxx_contention_t __monitor_val;
0126 if (__update_monitor_val_and_poll(__contention_address, __monitor_val))
0127 return true;
0128 std::__libcpp_atomic_wait(__contention_address, __monitor_val);
0129 } else if (__elapsed > chrono::microseconds(4))
0130 __libcpp_thread_yield();
0131 else {
0132 }
0133 return false;
0134 }
0135 };
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 template <class _AtomicWaitable, class _Poll>
0146 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0147 __atomic_wait_unless(const _AtomicWaitable& __a, _Poll&& __poll, memory_order __order) {
0148 static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
0149 __atomic_wait_poll_impl<_AtomicWaitable, __decay_t<_Poll> > __poll_impl = {__a, __poll, __order};
0150 __atomic_wait_backoff_impl<_AtomicWaitable, __decay_t<_Poll> > __backoff_fn = {__a, __poll, __order};
0151 std::__libcpp_thread_poll_with_backoff(__poll_impl, __backoff_fn);
0152 }
0153
0154 template <class _AtomicWaitable>
0155 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) {
0156 static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
0157 std::__cxx_atomic_notify_one(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a));
0158 }
0159
0160 template <class _AtomicWaitable>
0161 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) {
0162 static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
0163 std::__cxx_atomic_notify_all(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a));
0164 }
0165
0166 #else
0167
0168 template <class _AtomicWaitable, class _Poll>
0169 _LIBCPP_HIDE_FROM_ABI void __atomic_wait_unless(const _AtomicWaitable& __a, _Poll&& __poll, memory_order __order) {
0170 __atomic_wait_poll_impl<_AtomicWaitable, __decay_t<_Poll> > __poll_fn = {__a, __poll, __order};
0171 std::__libcpp_thread_poll_with_backoff(__poll_fn, __spinning_backoff_policy());
0172 }
0173
0174 template <class _AtomicWaitable>
0175 _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable&) {}
0176
0177 template <class _AtomicWaitable>
0178 _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable&) {}
0179
0180 #endif
0181
0182 template <typename _Tp>
0183 _LIBCPP_HIDE_FROM_ABI bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp const& __rhs) {
0184 return std::memcmp(std::addressof(__lhs), std::addressof(__rhs), sizeof(_Tp)) == 0;
0185 }
0186
0187 template <class _Tp>
0188 struct __atomic_compare_unequal_to {
0189 _Tp __val_;
0190 _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __arg) const {
0191 return !std::__cxx_nonatomic_compare_equal(__arg, __val_);
0192 }
0193 };
0194
0195 template <class _AtomicWaitable, class _Up>
0196 _LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void
0197 __atomic_wait(_AtomicWaitable& __a, _Up __val, memory_order __order) {
0198 static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
0199 __atomic_compare_unequal_to<_Up> __nonatomic_equal = {__val};
0200 std::__atomic_wait_unless(__a, __nonatomic_equal, __order);
0201 }
0202
0203 _LIBCPP_END_NAMESPACE_STD
0204
0205 #endif