[libcxx-commits] [libcxx] [libc++] refactor atomic_waitable_traits into its own header and remove pre 20 support (PR #173157)

via libcxx-commits libcxx-commits at lists.llvm.org
Sat Dec 20 10:39:48 PST 2025


https://github.com/huixie90 updated https://github.com/llvm/llvm-project/pull/173157

>From c36bbf4c90c4c80a6475ae658f7af0b6793fdbeb Mon Sep 17 00:00:00 2001
From: Hui Xie <hui.xie1990 at gmail.com>
Date: Sat, 20 Dec 2025 16:03:13 +0000
Subject: [PATCH 1/3] [libc++] make atomic_waitable_traits in its own header

---
 libcxx/include/CMakeLists.txt                 |   1 +
 libcxx/include/__atomic/atomic.h              |   1 +
 libcxx/include/__atomic/atomic_flag.h         |   1 +
 libcxx/include/__atomic/atomic_ref.h          |   1 +
 libcxx/include/__atomic/atomic_sync.h         |  73 +------------
 .../include/__atomic/atomic_waitable_traits.h | 101 ++++++++++++++++++
 libcxx/include/atomic                         |   1 +
 libcxx/include/module.modulemap.in            |   1 +
 8 files changed, 108 insertions(+), 72 deletions(-)
 create mode 100644 libcxx/include/__atomic/atomic_waitable_traits.h

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 9df40eab678a2..914601d2ec651 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -214,6 +214,7 @@ set(files
   __atomic/atomic_lock_free.h
   __atomic/atomic_ref.h
   __atomic/atomic_sync.h
+  __atomic/atomic_waitable_traits.h
   __atomic/check_memory_order.h
   __atomic/contention_t.h
   __atomic/fence.h
diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index 554c111d695f2..fbd17eff75d36 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -10,6 +10,7 @@
 #define _LIBCPP___ATOMIC_ATOMIC_H
 
 #include <__atomic/atomic_sync.h>
+#include <__atomic/atomic_waitable_traits.h>
 #include <__atomic/check_memory_order.h>
 #include <__atomic/floating_point_helper.h>
 #include <__atomic/is_always_lock_free.h>
diff --git a/libcxx/include/__atomic/atomic_flag.h b/libcxx/include/__atomic/atomic_flag.h
index 321a6283ba7ad..f78301256820e 100644
--- a/libcxx/include/__atomic/atomic_flag.h
+++ b/libcxx/include/__atomic/atomic_flag.h
@@ -10,6 +10,7 @@
 #define _LIBCPP___ATOMIC_ATOMIC_FLAG_H
 
 #include <__atomic/atomic_sync.h>
+#include <__atomic/atomic_waitable_traits.h>
 #include <__atomic/contention_t.h>
 #include <__atomic/memory_order.h>
 #include <__atomic/support.h>
diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h
index 9a36aaa3b84fe..b00685f7ce74c 100644
--- a/libcxx/include/__atomic/atomic_ref.h
+++ b/libcxx/include/__atomic/atomic_ref.h
@@ -19,6 +19,7 @@
 
 #include <__assert>
 #include <__atomic/atomic_sync.h>
+#include <__atomic/atomic_waitable_traits.h>
 #include <__atomic/check_memory_order.h>
 #include <__atomic/floating_point_helper.h>
 #include <__atomic/memory_order.h>
diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h
index d0119ab5d35ec..3bd4b2eb0303d 100644
--- a/libcxx/include/__atomic/atomic_sync.h
+++ b/libcxx/include/__atomic/atomic_sync.h
@@ -9,6 +9,7 @@
 #ifndef _LIBCPP___ATOMIC_ATOMIC_SYNC_H
 #define _LIBCPP___ATOMIC_ATOMIC_SYNC_H
 
+#include <__atomic/atomic_waitable_traits.h>
 #include <__atomic/contention_t.h>
 #include <__atomic/memory_order.h>
 #include <__atomic/to_gcc_order.h>
@@ -18,10 +19,8 @@
 #include <__thread/poll_with_backoff.h>
 #include <__type_traits/conjunction.h>
 #include <__type_traits/decay.h>
-#include <__type_traits/has_unique_object_representation.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_same.h>
-#include <__type_traits/is_trivially_copyable.h>
 #include <__type_traits/void_t.h>
 #include <__utility/declval.h>
 #include <cstring>
@@ -32,34 +31,6 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-// The customisation points to enable the following functions:
-// - __atomic_wait
-// - __atomic_wait_unless
-// - __atomic_notify_one
-// - __atomic_notify_all
-// Note that std::atomic<T>::wait was back-ported to C++03
-// The below implementations look ugly to support C++03
-template <class _Tp, class = void>
-struct __atomic_waitable_traits {
-  using __value_type _LIBCPP_NODEBUG = void;
-
-  template <class _AtomicWaitable>
-  static void __atomic_load(_AtomicWaitable&&, memory_order) = delete;
-
-  template <class _AtomicWaitable>
-  static void __atomic_contention_address(_AtomicWaitable&&) = delete;
-};
-
-template <class _Tp, class = void>
-struct __atomic_waitable : false_type {};
-
-template <class _Tp>
-struct __atomic_waitable< _Tp,
-                          __void_t<decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(
-                                       std::declval<const _Tp&>(), std::declval<memory_order>())),
-                                   decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(
-                                       std::declval<const _Tp&>()))> > : true_type {};
-
 #if _LIBCPP_STD_VER >= 20
 #  if _LIBCPP_HAS_THREADS
 
@@ -108,48 +79,6 @@ _LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_notify_one
 template <std::size_t _Size>
 _LIBCPP_AVAILABILITY_NEW_SYNC _LIBCPP_EXPORTED_FROM_ABI void __atomic_notify_all_native(const void*) _NOEXCEPT;
 
-#    ifdef __linux__
-#      define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(4)
-#    elif defined(__APPLE__)
-#      define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY)                                                               \
-        _APPLY(4)                                                                                                      \
-        _APPLY(8)
-#    elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
-#      define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
-#    elif defined(_WIN32)
-#      define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
-#    else
-#      define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(sizeof(__cxx_contention_t))
-#    endif // __linux__
-
-// concepts defines the types are supported natively by the platform's wait
-
-#    if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
-
-_LIBCPP_HIDE_FROM_ABI constexpr bool __has_native_atomic_wait_impl(size_t __size) {
-  switch (__size) {
-#      define _LIBCPP_MAKE_CASE(n)                                                                                     \
-      case n:                                                                                                          \
-        return true;
-    _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_LIBCPP_MAKE_CASE)
-  default:
-    return false;
-#      undef _LIBCPP_MAKE_CASE
-  };
-}
-
-template <class _Tp>
-concept __has_native_atomic_wait =
-    has_unique_object_representations_v<_Tp> && is_trivially_copyable_v<_Tp> &&
-    __has_native_atomic_wait_impl(sizeof(_Tp));
-
-#    else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
-
-template <class _Tp>
-concept __has_native_atomic_wait = is_same_v<_Tp, __cxx_contention_t>;
-
-#    endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
-
 #    if _LIBCPP_AVAILABILITY_HAS_NEW_SYNC
 
 template <class _AtomicWaitable, class _Poll>
diff --git a/libcxx/include/__atomic/atomic_waitable_traits.h b/libcxx/include/__atomic/atomic_waitable_traits.h
new file mode 100644
index 0000000000000..5ff6da1e54ca5
--- /dev/null
+++ b/libcxx/include/__atomic/atomic_waitable_traits.h
@@ -0,0 +1,101 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___ATOMIC_ATOMIC_WAITABLE_TRAITS_H
+#define _LIBCPP___ATOMIC_ATOMIC_WAITABLE_TRAITS_H
+
+#include <__atomic/contention_t.h>
+#include <__atomic/memory_order.h>
+#include <__config>
+#include <__type_traits/decay.h>
+#include <__type_traits/has_unique_object_representation.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/is_trivially_copyable.h>
+#include <__type_traits/void_t.h>
+#include <__utility/declval.h>
+#include <cstring>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// The customisation points to enable the following functions:
+// - __atomic_wait
+// - __atomic_wait_unless
+// - __atomic_notify_one
+// - __atomic_notify_all
+// Note that std::atomic<T>::wait was back-ported to C++03
+// The below implementations look ugly to support C++03
+template <class _Tp, class = void>
+struct __atomic_waitable_traits {
+  using __value_type _LIBCPP_NODEBUG = void;
+
+  template <class _AtomicWaitable>
+  static void __atomic_load(_AtomicWaitable&&, memory_order) = delete;
+
+  template <class _AtomicWaitable>
+  static void __atomic_contention_address(_AtomicWaitable&&) = delete;
+};
+
+template <class _Tp, class = void>
+struct __atomic_waitable : false_type {};
+
+template <class _Tp>
+struct __atomic_waitable< _Tp,
+                          __void_t<decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(
+                                       std::declval<const _Tp&>(), std::declval<memory_order>())),
+                                   decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(
+                                       std::declval<const _Tp&>()))> > : true_type {};
+
+#ifdef __linux__
+#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(4)
+#elif defined(__APPLE__)
+#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY)                                                                   \
+    _APPLY(4)                                                                                                          \
+    _APPLY(8)
+#elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
+#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
+#elif defined(_WIN32)
+#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
+#else
+#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(sizeof(__cxx_contention_t))
+#endif // __linux__
+
+// concepts defines the types are supported natively by the platform's wait
+
+#if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
+
+_LIBCPP_HIDE_FROM_ABI constexpr bool __has_native_atomic_wait_impl(size_t __size) {
+  switch (__size) {
+#  define _LIBCPP_MAKE_CASE(n)                                                                                         \
+  case n:                                                                                                              \
+    return true;
+    _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_LIBCPP_MAKE_CASE)
+  default:
+    return false;
+#  undef _LIBCPP_MAKE_CASE
+  };
+}
+
+template <class _Tp>
+concept __has_native_atomic_wait =
+    has_unique_object_representations_v<_Tp> && is_trivially_copyable_v<_Tp> &&
+    __has_native_atomic_wait_impl(sizeof(_Tp));
+
+#else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
+
+template <class _Tp>
+concept __has_native_atomic_wait = is_same_v<_Tp, __cxx_contention_t>;
+
+#endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___ATOMIC_ATOMIC_WAITABLE_TRAITS_H
diff --git a/libcxx/include/atomic b/libcxx/include/atomic
index 75af5de33ca4c..39308bfe8aa27 100644
--- a/libcxx/include/atomic
+++ b/libcxx/include/atomic
@@ -607,6 +607,7 @@ template <class T>
 #  include <__atomic/atomic_flag.h>
 #  include <__atomic/atomic_init.h>
 #  include <__atomic/atomic_lock_free.h>
+#  include <__atomic/atomic_waitable_traits.h>
 #  include <__atomic/atomic_sync.h>
 #  include <__atomic/check_memory_order.h>
 #  include <__atomic/contention_t.h>
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index ce168f77dfea4..e24e83420405d 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -869,6 +869,7 @@ module std [system] {
     module atomic_lock_free       { header "__atomic/atomic_lock_free.h" }
     module atomic_ref             { header "__atomic/atomic_ref.h" }
     module atomic_sync            { header "__atomic/atomic_sync.h" }
+    module atomic_waitable_traits { header "__atomic/atomic_waitable_traits.h" }
     module atomic {
       header "__atomic/atomic.h"
       export std.atomic.atomic_base // most of std::atomic methods are defined there

>From 2b6fe5c0fa3a6347f583c5481c831a0f8b95835a Mon Sep 17 00:00:00 2001
From: Hui Xie <hui.xie1990 at gmail.com>
Date: Sat, 20 Dec 2025 16:46:50 +0000
Subject: [PATCH 2/3] remove pre 20 support

---
 libcxx/include/__atomic/atomic.h              |  5 +-
 libcxx/include/__atomic/atomic_flag.h         |  2 +
 libcxx/include/__atomic/atomic_sync.h         | 12 ++--
 .../include/__atomic/atomic_waitable_traits.h | 61 +++++++++----------
 4 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index fbd17eff75d36..b98620a864052 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -201,6 +201,7 @@ struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
   _LIBCPP_HIDE_FROM_ABI _Tp operator^=(_Tp __op) _NOEXCEPT { return fetch_xor(__op) ^ __op; }
 };
 
+#if _LIBCPP_STD_VER >= 20
 // Here we need _IsIntegral because the default template argument is not enough
 // e.g  __atomic_base<int> is __atomic_base<int, true>, which inherits from
 // __atomic_base<int, false> and the caller of the wait function is
@@ -229,6 +230,8 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
   }
 };
 
+#endif // _LIBCPP_STD_VER >= 20
+
 template <typename _Tp>
 struct __check_atomic_mandates {
   using type _LIBCPP_NODEBUG = _Tp;
@@ -322,10 +325,10 @@ struct atomic<_Tp*> : public __atomic_base<_Tp*> {
   atomic& operator=(const atomic&) volatile = delete;
 };
 
+#if _LIBCPP_STD_VER >= 20
 template <class _Tp>
 struct __atomic_waitable_traits<atomic<_Tp> > : __atomic_waitable_traits<__atomic_base<_Tp> > {};
 
-#if _LIBCPP_STD_VER >= 20
 template <class _Tp>
   requires is_floating_point_v<_Tp>
 struct atomic<_Tp> : __atomic_base<_Tp> {
diff --git a/libcxx/include/__atomic/atomic_flag.h b/libcxx/include/__atomic/atomic_flag.h
index f78301256820e..42864c869d22f 100644
--- a/libcxx/include/__atomic/atomic_flag.h
+++ b/libcxx/include/__atomic/atomic_flag.h
@@ -75,6 +75,7 @@ struct atomic_flag {
   atomic_flag& operator=(const atomic_flag&) volatile = delete;
 };
 
+#if _LIBCPP_STD_VER >= 20
 template <>
 struct __atomic_waitable_traits<atomic_flag> {
   using __value_type _LIBCPP_NODEBUG = _LIBCPP_ATOMIC_FLAG_TYPE;
@@ -98,6 +99,7 @@ struct __atomic_waitable_traits<atomic_flag> {
     return std::addressof(__a.__a_);
   }
 };
+#endif // _LIBCPP_STD_VER >= 20
 
 inline _LIBCPP_HIDE_FROM_ABI bool atomic_flag_test(const volatile atomic_flag* __o) _NOEXCEPT { return __o->test(); }
 
diff --git a/libcxx/include/__atomic/atomic_sync.h b/libcxx/include/__atomic/atomic_sync.h
index 3bd4b2eb0303d..9f46dfe65bb0d 100644
--- a/libcxx/include/__atomic/atomic_sync.h
+++ b/libcxx/include/__atomic/atomic_sync.h
@@ -169,7 +169,7 @@ struct __atomic_wait_backoff_impl {
 // value. The predicate function must not return `false` spuriously.
 template <class _AtomicWaitable, class _Poll>
 _LIBCPP_HIDE_FROM_ABI void __atomic_wait_unless(const _AtomicWaitable& __a, memory_order __order, _Poll&& __poll) {
-  static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
+  static_assert(__atomic_waitable<_AtomicWaitable>);
   __atomic_wait_backoff_impl<_AtomicWaitable, __decay_t<_Poll> > __backoff_fn = {__a, __poll, __order};
   std::__libcpp_thread_poll_with_backoff(
       /* poll */
@@ -184,7 +184,7 @@ _LIBCPP_HIDE_FROM_ABI void __atomic_wait_unless(const _AtomicWaitable& __a, memo
 
 template <class _AtomicWaitable>
 _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) {
-  static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
+  static_assert(__atomic_waitable<_AtomicWaitable>);
   using __value_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__value_type;
   using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
   auto __contention_address =
@@ -198,7 +198,7 @@ _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) {
 
 template <class _AtomicWaitable>
 _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) {
-  static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
+  static_assert(__atomic_waitable<_AtomicWaitable>);
   using __value_type _LIBCPP_NODEBUG = typename __atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__value_type;
   using __waitable_traits _LIBCPP_NODEBUG = __atomic_waitable_traits<__decay_t<_AtomicWaitable> >;
   auto __contention_address =
@@ -214,13 +214,13 @@ _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) {
 
 template <class _AtomicWaitable>
 _LIBCPP_HIDE_FROM_ABI void __atomic_notify_one(const _AtomicWaitable& __a) {
-  static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
+  static_assert(__atomic_waitable<_AtomicWaitable>);
   std::__cxx_atomic_notify_one(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a));
 }
 
 template <class _AtomicWaitable>
 _LIBCPP_HIDE_FROM_ABI void __atomic_notify_all(const _AtomicWaitable& __a) {
-  static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
+  static_assert(__atomic_waitable<_AtomicWaitable>);
   std::__cxx_atomic_notify_all(__atomic_waitable_traits<__decay_t<_AtomicWaitable> >::__atomic_contention_address(__a));
 }
 
@@ -254,7 +254,7 @@ _LIBCPP_HIDE_FROM_ABI bool __cxx_nonatomic_compare_equal(_Tp const& __lhs, _Tp c
 
 template <class _AtomicWaitable, class _Tp>
 _LIBCPP_HIDE_FROM_ABI void __atomic_wait(_AtomicWaitable& __a, _Tp __val, memory_order __order) {
-  static_assert(__atomic_waitable<_AtomicWaitable>::value, "");
+  static_assert(__atomic_waitable<_AtomicWaitable>);
   std::__atomic_wait_unless(__a, __order, [&](_Tp const& __current) {
     return !std::__cxx_nonatomic_compare_equal(__current, __val);
   });
diff --git a/libcxx/include/__atomic/atomic_waitable_traits.h b/libcxx/include/__atomic/atomic_waitable_traits.h
index 5ff6da1e54ca5..de06fe70b3e1a 100644
--- a/libcxx/include/__atomic/atomic_waitable_traits.h
+++ b/libcxx/include/__atomic/atomic_waitable_traits.h
@@ -26,13 +26,13 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if _LIBCPP_STD_VER >= 20
+
 // The customisation points to enable the following functions:
 // - __atomic_wait
 // - __atomic_wait_unless
 // - __atomic_notify_one
 // - __atomic_notify_all
-// Note that std::atomic<T>::wait was back-ported to C++03
-// The below implementations look ugly to support C++03
 template <class _Tp, class = void>
 struct __atomic_waitable_traits {
   using __value_type _LIBCPP_NODEBUG = void;
@@ -44,43 +44,40 @@ struct __atomic_waitable_traits {
   static void __atomic_contention_address(_AtomicWaitable&&) = delete;
 };
 
-template <class _Tp, class = void>
-struct __atomic_waitable : false_type {};
-
 template <class _Tp>
-struct __atomic_waitable< _Tp,
-                          __void_t<decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(
-                                       std::declval<const _Tp&>(), std::declval<memory_order>())),
-                                   decltype(__atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(
-                                       std::declval<const _Tp&>()))> > : true_type {};
-
-#ifdef __linux__
-#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(4)
-#elif defined(__APPLE__)
-#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY)                                                                   \
-    _APPLY(4)                                                                                                          \
-    _APPLY(8)
-#elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
-#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
-#elif defined(_WIN32)
-#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
-#else
-#  define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(sizeof(__cxx_contention_t))
-#endif // __linux__
+concept __atomic_waitable = requires(const _Tp __t, memory_order __order) {
+  typename __atomic_waitable_traits<__decay_t<_Tp> >::__value_type;
+  { __atomic_waitable_traits<__decay_t<_Tp> >::__atomic_load(__t, __order) };
+  { __atomic_waitable_traits<__decay_t<_Tp> >::__atomic_contention_address(__t) };
+};
+
+#  ifdef __linux__
+#    define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(4)
+#  elif defined(__APPLE__)
+#    define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY)                                                                 \
+      _APPLY(4)                                                                                                        \
+      _APPLY(8)
+#  elif defined(__FreeBSD__) && __SIZEOF_LONG__ == 8
+#    define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
+#  elif defined(_WIN32)
+#    define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(8)
+#  else
+#    define _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_APPLY) _APPLY(sizeof(__cxx_contention_t))
+#  endif // __linux__
 
 // concepts defines the types are supported natively by the platform's wait
 
-#if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
+#  if defined(_LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE)
 
 _LIBCPP_HIDE_FROM_ABI constexpr bool __has_native_atomic_wait_impl(size_t __size) {
   switch (__size) {
-#  define _LIBCPP_MAKE_CASE(n)                                                                                         \
-  case n:                                                                                                              \
-    return true;
+#    define _LIBCPP_MAKE_CASE(n)                                                                                       \
+    case n:                                                                                                            \
+      return true;
     _LIBCPP_NATIVE_PLATFORM_WAIT_SIZES(_LIBCPP_MAKE_CASE)
   default:
     return false;
-#  undef _LIBCPP_MAKE_CASE
+#    undef _LIBCPP_MAKE_CASE
   };
 }
 
@@ -89,12 +86,14 @@ concept __has_native_atomic_wait =
     has_unique_object_representations_v<_Tp> && is_trivially_copyable_v<_Tp> &&
     __has_native_atomic_wait_impl(sizeof(_Tp));
 
-#else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
+#  else // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
 
 template <class _Tp>
 concept __has_native_atomic_wait = is_same_v<_Tp, __cxx_contention_t>;
 
-#endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
+#  endif // _LIBCPP_ABI_ATOMIC_WAIT_NATIVE_BY_SIZE
+
+#endif // C++20
 
 _LIBCPP_END_NAMESPACE_STD
 

>From 724a9454421860ed68995908414c7fb2fc4dd51a Mon Sep 17 00:00:00 2001
From: Hui Xie <hui.xie1990 at gmail.com>
Date: Sat, 20 Dec 2025 18:39:37 +0000
Subject: [PATCH 3/3] ci

---
 libcxx/include/CMakeLists.txt         | 2 +-
 libcxx/include/__atomic/atomic.h      | 2 +-
 libcxx/include/__atomic/atomic_flag.h | 2 +-
 libcxx/include/__atomic/atomic_ref.h  | 2 +-
 libcxx/include/module.modulemap.in    | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 914601d2ec651..dae03b08179af 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -213,8 +213,8 @@ set(files
   __atomic/atomic_init.h
   __atomic/atomic_lock_free.h
   __atomic/atomic_ref.h
-  __atomic/atomic_sync.h
   __atomic/atomic_waitable_traits.h
+  __atomic/atomic_sync.h
   __atomic/check_memory_order.h
   __atomic/contention_t.h
   __atomic/fence.h
diff --git a/libcxx/include/__atomic/atomic.h b/libcxx/include/__atomic/atomic.h
index b98620a864052..9bd2a95976192 100644
--- a/libcxx/include/__atomic/atomic.h
+++ b/libcxx/include/__atomic/atomic.h
@@ -9,8 +9,8 @@
 #ifndef _LIBCPP___ATOMIC_ATOMIC_H
 #define _LIBCPP___ATOMIC_ATOMIC_H
 
-#include <__atomic/atomic_sync.h>
 #include <__atomic/atomic_waitable_traits.h>
+#include <__atomic/atomic_sync.h>
 #include <__atomic/check_memory_order.h>
 #include <__atomic/floating_point_helper.h>
 #include <__atomic/is_always_lock_free.h>
diff --git a/libcxx/include/__atomic/atomic_flag.h b/libcxx/include/__atomic/atomic_flag.h
index 42864c869d22f..e0a9ab3699471 100644
--- a/libcxx/include/__atomic/atomic_flag.h
+++ b/libcxx/include/__atomic/atomic_flag.h
@@ -9,8 +9,8 @@
 #ifndef _LIBCPP___ATOMIC_ATOMIC_FLAG_H
 #define _LIBCPP___ATOMIC_ATOMIC_FLAG_H
 
-#include <__atomic/atomic_sync.h>
 #include <__atomic/atomic_waitable_traits.h>
+#include <__atomic/atomic_sync.h>
 #include <__atomic/contention_t.h>
 #include <__atomic/memory_order.h>
 #include <__atomic/support.h>
diff --git a/libcxx/include/__atomic/atomic_ref.h b/libcxx/include/__atomic/atomic_ref.h
index b00685f7ce74c..eac5317624524 100644
--- a/libcxx/include/__atomic/atomic_ref.h
+++ b/libcxx/include/__atomic/atomic_ref.h
@@ -18,8 +18,8 @@
 #define _LIBCPP___ATOMIC_ATOMIC_REF_H
 
 #include <__assert>
-#include <__atomic/atomic_sync.h>
 #include <__atomic/atomic_waitable_traits.h>
+#include <__atomic/atomic_sync.h>
 #include <__atomic/check_memory_order.h>
 #include <__atomic/floating_point_helper.h>
 #include <__atomic/memory_order.h>
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index e24e83420405d..75564c2d74c66 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -868,8 +868,8 @@ module std [system] {
     module atomic_init            { header "__atomic/atomic_init.h" }
     module atomic_lock_free       { header "__atomic/atomic_lock_free.h" }
     module atomic_ref             { header "__atomic/atomic_ref.h" }
-    module atomic_sync            { header "__atomic/atomic_sync.h" }
     module atomic_waitable_traits { header "__atomic/atomic_waitable_traits.h" }
+    module atomic_sync            { header "__atomic/atomic_sync.h" }
     module atomic {
       header "__atomic/atomic.h"
       export std.atomic.atomic_base // most of std::atomic methods are defined there



More information about the libcxx-commits mailing list