@@ -38,6 +38,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
38
38
// The below implementations look ugly to support C++03
39
39
template <class _Tp , class = void >
40
40
struct __atomic_waitable_traits {
41
+ using __inner_type _LIBCPP_NODEBUG = void ;
42
+
41
43
template <class _AtomicWaitable >
42
44
static void __atomic_load (_AtomicWaitable&&, memory_order) = delete;
43
45
@@ -58,21 +60,26 @@ struct __atomic_waitable< _Tp,
58
60
#if _LIBCPP_STD_VER >= 20
59
61
# if _LIBCPP_HAS_THREADS
60
62
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>
65
64
_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;
67
69
68
70
_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>
70
77
_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>
74
81
_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;
76
83
77
84
template <class _AtomicWaitable , class _Poll >
78
85
struct __atomic_wait_backoff_impl {
@@ -81,38 +88,25 @@ struct __atomic_wait_backoff_impl {
81
88
memory_order __order_;
82
89
83
90
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;
107
92
108
93
_LIBCPP_AVAILABILITY_SYNC
109
94
_LIBCPP_HIDE_FROM_ABI bool operator ()(chrono::nanoseconds __elapsed) const {
110
95
if (__elapsed > chrono::microseconds (4 )) {
111
96
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
+ }
116
110
} else {
117
111
} // poll
118
112
return false ;
@@ -144,13 +138,23 @@ __atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& _
144
138
template <class _AtomicWaitable >
145
139
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one (const _AtomicWaitable& __a) {
146
140
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
+ }
148
147
}
149
148
150
149
template <class _AtomicWaitable >
151
150
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all (const _AtomicWaitable& __a) {
152
151
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
+ }
154
158
}
155
159
156
160
# else // _LIBCPP_HAS_THREADS
0 commit comments