@@ -38,6 +38,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
3838// The below implementations look ugly to support C++03
3939template <class _Tp , class = void >
4040struct __atomic_waitable_traits {
41+ using __inner_type _LIBCPP_NODEBUG = void ;
42+
4143 template <class _AtomicWaitable >
4244 static void __atomic_load (_AtomicWaitable&&, memory_order) = delete;
4345
@@ -58,21 +60,26 @@ struct __atomic_waitable< _Tp,
5860#if _LIBCPP_STD_VER >= 20
5961# if _LIBCPP_HAS_THREADS
6062
61- _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one (void const volatile *) _NOEXCEPT;
62- _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all (void const volatile *) _NOEXCEPT;
63- _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
64- __libcpp_atomic_monitor (void const volatile *) _NOEXCEPT;
63+ template <std::size_t _Size>
6564_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
66- __libcpp_atomic_wait (void const volatile *, __cxx_contention_t ) _NOEXCEPT;
65+ __libcpp_atomic_wait_native (void const volatile * __address, void const volatile * __old_value) _NOEXCEPT;
66+
67+ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
68+ __libcpp_atomic_monitor_global (void const volatile * __address) _NOEXCEPT;
6769
6870_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
69- __cxx_atomic_notify_one (__cxx_atomic_contention_t const volatile *) _NOEXCEPT;
71+ __libcpp_atomic_wait_global_table (void const volatile * __address, __cxx_contention_t __monitor_value) _NOEXCEPT;
72+
73+ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_one_global_table (void const volatile *) _NOEXCEPT;
74+ _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void __cxx_atomic_notify_all_global_table (void const volatile *) _NOEXCEPT;
75+
76+ template <std::size_t _Size>
7077_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
71- __cxx_atomic_notify_all ( __cxx_atomic_contention_t const volatile *) _NOEXCEPT;
72- _LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t
73- __libcpp_atomic_monitor ( __cxx_atomic_contention_t const volatile *) _NOEXCEPT;
78+ __cxx_atomic_notify_one_native ( const volatile void *) _NOEXCEPT;
79+
80+ template <std:: size_t _Size>
7481_LIBCPP_AVAILABILITY_SYNC _LIBCPP_EXPORTED_FROM_ABI void
75- __libcpp_atomic_wait ( __cxx_atomic_contention_t const volatile *, __cxx_contention_t ) _NOEXCEPT;
82+ __cxx_atomic_notify_all_native ( const volatile void * ) _NOEXCEPT;
7683
7784template <class _AtomicWaitable , class _Poll >
7885struct __atomic_wait_backoff_impl {
@@ -81,38 +88,25 @@ struct __atomic_wait_backoff_impl {
8188 memory_order __order_;
8289
8390 using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t <_AtomicWaitable> >;
84-
85- _LIBCPP_AVAILABILITY_SYNC
86- _LIBCPP_HIDE_FROM_ABI bool
87- __update_monitor_val_and_poll (__cxx_atomic_contention_t const volatile *, __cxx_contention_t & __monitor_val) const {
88- // In case the contention type happens to be __cxx_atomic_contention_t, i.e. __cxx_atomic_impl<int64_t>,
89- // the platform wait is directly monitoring the atomic value itself.
90- // `__poll_` takes the current value of the atomic as an in-out argument
91- // to potentially modify it. After it returns, `__monitor` has a value
92- // which can be safely waited on by `std::__libcpp_atomic_wait` without any
93- // ABA style issues.
94- __monitor_val = __waitable_traits::__atomic_load (__a_, __order_);
95- return __poll_ (__monitor_val);
96- }
97-
98- _LIBCPP_AVAILABILITY_SYNC
99- _LIBCPP_HIDE_FROM_ABI bool
100- __update_monitor_val_and_poll (void const volatile * __contention_address, __cxx_contention_t & __monitor_val) const {
101- // In case the contention type is anything else, platform wait is monitoring a __cxx_atomic_contention_t
102- // from the global pool, the monitor comes from __libcpp_atomic_monitor
103- __monitor_val = std::__libcpp_atomic_monitor (__contention_address);
104- auto __current_val = __waitable_traits::__atomic_load (__a_, __order_);
105- return __poll_ (__current_val);
106- }
91+ using __inner_type _LIBCPP_NODEBUG = typename __waitable_traits::__inner_type;
10792
10893 _LIBCPP_AVAILABILITY_SYNC
10994 _LIBCPP_HIDE_FROM_ABI bool operator ()(chrono::nanoseconds __elapsed) const {
11095 if (__elapsed > chrono::microseconds (4 )) {
11196 auto __contention_address = __waitable_traits::__atomic_contention_address (__a_);
112- __cxx_contention_t __monitor_val;
113- if (__update_monitor_val_and_poll (__contention_address, __monitor_val))
114- return true ;
115- std::__libcpp_atomic_wait (__contention_address, __monitor_val);
97+
98+ if constexpr (__is_atomic_wait_native_type<__inner_type>::value) {
99+ auto __atomic_value = __waitable_traits::__atomic_load (__a_, __order_);
100+ if (__poll_ (__atomic_value))
101+ return true ;
102+ std::__libcpp_atomic_wait_native<sizeof (__inner_type)>(__contention_address, &__atomic_value);
103+ } else {
104+ __cxx_contention_t __monitor_val = std::__libcpp_atomic_monitor_global (__contention_address);
105+ auto __atomic_value = __waitable_traits::__atomic_load (__a_, __order_);
106+ if (__poll_ (__atomic_value))
107+ return true ;
108+ std::__libcpp_atomic_wait_global_table (__contention_address, __monitor_val);
109+ }
116110 } else {
117111 } // poll
118112 return false ;
@@ -144,13 +138,23 @@ __atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& _
144138template <class _AtomicWaitable >
145139_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one (const _AtomicWaitable& __a) {
146140 static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
147- std::__cxx_atomic_notify_one (__atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
141+ using __inner_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__inner_type;
142+ if constexpr (__is_atomic_wait_native_type<__inner_type>::value) {
143+ std::__cxx_atomic_notify_one_native<sizeof (__inner_type)>(__atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
144+ } else {
145+ std::__cxx_atomic_notify_one_global_table (__atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
146+ }
148147}
149148
150149template <class _AtomicWaitable >
151150_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all (const _AtomicWaitable& __a) {
152151 static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
153- std::__cxx_atomic_notify_all (__atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
152+ using __inner_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__inner_type;
153+ if constexpr (__is_atomic_wait_native_type<__inner_type>::value) {
154+ std::__cxx_atomic_notify_all_native<sizeof (__inner_type)>(__atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
155+ } else {
156+ std::__cxx_atomic_notify_all_global_table (__atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
157+ }
154158}
155159
156160# else // _LIBCPP_HAS_THREADS
0 commit comments