99#ifndef _LIBCPP___ATOMIC_ATOMIC_SYNC_H
1010#define _LIBCPP___ATOMIC_ATOMIC_SYNC_H
1111
12+ #include < __algorithm/ranges_find.h>
1213#include < __atomic/contention_t.h>
1314#include < __atomic/memory_order.h>
1415#include < __atomic/to_gcc_order.h>
1516#include < __chrono/duration.h>
1617#include < __config>
1718#include < __memory/addressof.h>
19+ #include < __ranges/access.h>
1820#include < __thread/poll_with_backoff.h>
1921#include < __type_traits/conjunction.h>
2022#include < __type_traits/decay.h>
23+ #include < __type_traits/has_unique_object_representation.h>
2124#include < __type_traits/invoke.h>
25+ #include < __type_traits/is_same.h>
2226#include < __type_traits/void_t.h>
2327#include < __utility/declval.h>
2428#include < cstring>
@@ -88,7 +92,7 @@ __libcpp_atomic_notify_all_global_table(void const volatile*) _NOEXCEPT;
8892template <std::size_t _Size>
8993_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void
9094
91- __libcpp_atomic_wait_native (void const volatile * __address, void const volatile * __old_value) _NOEXCEPT;
95+ __libcpp_atomic_wait_native (void const volatile * __address, void const * __old_value) _NOEXCEPT;
9296template <std::size_t _Size>
9397_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void
9498__libcpp_atomic_notify_one_native (const volatile void *) _NOEXCEPT;
@@ -97,6 +101,48 @@ template <std::size_t _Size>
97101_LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void
98102__libcpp_atomic_notify_all_native (const volatile void *) _NOEXCEPT;
99103
104+ // concepts defines the types are supported natively by the platform's wait
105+
106+ # if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
107+
108+ # ifdef __linux__
109+
110+ # define _LIBCPP_ATOMIC_WAIT_SIZES_LIST (_APPLY ) _APPLY(4 )
111+
112+ # elif defined(__APPLE__)
113+
114+ # define _LIBCPP_ATOMIC_WAIT_SIZES_LIST (_APPLY ) \
115+ _APPLY (4 ) \
116+ _APPLY(8 )
117+
118+ # elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
119+
120+ # define _LIBCPP_ATOMIC_WAIT_SIZES_LIST (_APPLY ) _APPLY(8 )
121+
122+ # else
123+
124+ # define _LIBCPP_ATOMIC_WAIT_SIZES_LIST (_APPLY ) _APPLY(sizeof (__cxx_contention_t ))
125+
126+ # endif // __linux__
127+
128+ inline constexpr std::size_t __supported_native_wait_sizes[] = {
129+ # define _IDENTITY (_SIZE ) _SIZE,
130+ _LIBCPP_ATOMIC_WAIT_SIZES_LIST (_IDENTITY)
131+ # undef _IDENTITY
132+ };
133+
134+ template <class _Tp >
135+ concept __atomic_wait_native_type =
136+ has_unique_object_representations_v<_Tp> &&
137+ std::ranges::find (__supported_native_wait_sizes, sizeof (_Tp)) != ranges::end(__supported_native_wait_sizes);
138+
139+ # else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
140+
141+ template <class _Tp >
142+ concept __atomic_wait_native_type = is_same_v<_Tp, __cxx_contention_t >;
143+
144+ # endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
145+
100146template <class _AtomicWaitable , class _Poll >
101147struct __atomic_wait_backoff_impl {
102148 const _AtomicWaitable& __a_;
@@ -110,7 +156,7 @@ struct __atomic_wait_backoff_impl {
110156 if (__elapsed > chrono::microseconds (4 )) {
111157 auto __contention_address = __waitable_traits::__atomic_contention_address (__a_);
112158
113- if constexpr (__is_atomic_wait_native_type <__value_type>::value ) {
159+ if constexpr (__atomic_wait_native_type <__value_type>) {
114160 auto __atomic_value = __waitable_traits::__atomic_load (__a_, __order_);
115161 if (__poll_ (__atomic_value))
116162 return true ;
@@ -153,7 +199,7 @@ template <class _AtomicWaitable>
153199_LIBCPP_HIDE_FROM_ABI void __atomic_notify_one (const _AtomicWaitable& __a) {
154200 static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
155201 using __value_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__value_type;
156- if constexpr (__is_atomic_wait_native_type <__value_type>::value ) {
202+ if constexpr (__atomic_wait_native_type <__value_type>) {
157203 std::__libcpp_atomic_notify_one_native<sizeof (__value_type)>(
158204 __atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
159205 } else {
@@ -166,7 +212,7 @@ template <class _AtomicWaitable>
166212_LIBCPP_HIDE_FROM_ABI void __atomic_notify_all (const _AtomicWaitable& __a) {
167213 static_assert (__atomic_waitable<_AtomicWaitable>::value, " " );
168214 using __value_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__value_type;
169- if constexpr (__is_atomic_wait_native_type <__value_type>::value ) {
215+ if constexpr (__atomic_wait_native_type <__value_type>) {
170216 std::__libcpp_atomic_notify_all_native<sizeof (__value_type)>(
171217 __atomic_waitable_traits<__decay_t <_AtomicWaitable> >::__atomic_contention_address (__a));
172218 } else {
0 commit comments