[libcxx-commits] [libcxx] 6f0c52e - [libc++] Refactor atomic_{unsigned, signed}_lock_free (#73041)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Nov 22 11:55:20 PST 2023
Author: Louis Dionne
Date: 2023-11-22T14:54:40-05:00
New Revision: 6f0c52e56fb7f237ed8071573ce8a2021b4c7289
URL: https://github.com/llvm/llvm-project/commit/6f0c52e56fb7f237ed8071573ce8a2021b4c7289
DIFF: https://github.com/llvm/llvm-project/commit/6f0c52e56fb7f237ed8071573ce8a2021b4c7289.diff
LOG: [libc++] Refactor atomic_{unsigned,signed}_lock_free (#73041)
Their definition was a bit roundabout and it was actually wrong since
atomic_unsigned_lock_free would be a signed type whenever
__cxx_contention_t is lock free, which is most of the time.
Fixes #72968
Added:
Modified:
libcxx/include/__atomic/aliases.h
libcxx/include/atomic
libcxx/test/std/atomics/types.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__atomic/aliases.h b/libcxx/include/__atomic/aliases.h
index e2f9fae4094ef23..0fa289de54b0f12 100644
--- a/libcxx/include/__atomic/aliases.h
+++ b/libcxx/include/__atomic/aliases.h
@@ -15,6 +15,7 @@
#include <__atomic/is_always_lock_free.h>
#include <__config>
#include <__type_traits/conditional.h>
+#include <__type_traits/make_unsigned.h>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
@@ -80,36 +81,30 @@ using atomic_ptr
diff _t = atomic<ptr
diff _t>;
using atomic_intmax_t = atomic<intmax_t>;
using atomic_uintmax_t = atomic<uintmax_t>;
-// atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type
+// C++20 atomic_{signed,unsigned}_lock_free: prefer the contention type most highly, then the largest lock-free type
+#if _LIBCPP_STD_VER >= 20
+# if ATOMIC_LLONG_LOCK_FREE == 2
+using __largest_lock_free_type = long long;
+# elif ATOMIC_INT_LOCK_FREE == 2
+using __largest_lock_free_type = int;
+# elif ATOMIC_SHORT_LOCK_FREE == 2
+using __largest_lock_free_type = short;
+# elif ATOMIC_CHAR_LOCK_FREE == 2
+using __largest_lock_free_type = char;
+# else
+# define _LIBCPP_NO_LOCK_FREE_TYPES // There are no lockfree types (this can happen in freestanding)
+# endif
-#if _LIBCPP_STD_VER >= 17
-# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value
-#else
-# define _LIBCPP_CONTENTION_LOCK_FREE false
-#endif
-
-#if ATOMIC_LLONG_LOCK_FREE == 2
-using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, long long>;
-using __libcpp_unsigned_lock_free =
- __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned long long>;
-#elif ATOMIC_INT_LOCK_FREE == 2
-using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, int>;
-using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned int>;
-#elif ATOMIC_SHORT_LOCK_FREE == 2
-using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, short>;
-using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned short>;
-#elif ATOMIC_CHAR_LOCK_FREE == 2
-using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char>;
-using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char>;
-#else
-// No signed/unsigned lock-free types
-# define _LIBCPP_NO_LOCK_FREE_TYPES
-#endif
+# ifndef _LIBCPP_NO_LOCK_FREE_TYPES
+using __contention_t_or_largest =
+ __conditional_t<__libcpp_is_always_lock_free<__cxx_contention_t>::__value,
+ __cxx_contention_t,
+ __largest_lock_free_type>;
-#if !defined(_LIBCPP_NO_LOCK_FREE_TYPES)
-using atomic_signed_lock_free = atomic<__libcpp_signed_lock_free>;
-using atomic_unsigned_lock_free = atomic<__libcpp_unsigned_lock_free>;
-#endif
+using atomic_signed_lock_free = atomic<__contention_t_or_largest>;
+using atomic_unsigned_lock_free = atomic<make_unsigned_t<__contention_t_or_largest>>;
+# endif // !_LIBCPP_NO_LOCK_FREE_TYPES
+#endif // C++20
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/atomic b/libcxx/include/atomic
index 7bed8fd8bacfc5c..2e8f5b521a55eb6 100644
--- a/libcxx/include/atomic
+++ b/libcxx/include/atomic
@@ -514,6 +514,9 @@ typedef atomic<ptr
diff _t> atomic_ptr
diff _t;
typedef atomic<intmax_t> atomic_intmax_t;
typedef atomic<uintmax_t> atomic_uintmax_t;
+typedef see-below atomic_signed_lock_free; // since C++20
+typedef see-below atomic_unsigned_lock_free; // since C++20
+
// flag type and operations
typedef struct atomic_flag
diff --git a/libcxx/test/std/atomics/types.pass.cpp b/libcxx/test/std/atomics/types.pass.cpp
index deaa45dcddcaa16..cebf66ee7f1af03 100644
--- a/libcxx/test/std/atomics/types.pass.cpp
+++ b/libcxx/test/std/atomics/types.pass.cpp
@@ -175,7 +175,12 @@ int main(int, char**)
#if TEST_STD_VER >= 20
test<std::atomic_signed_lock_free::value_type>();
+ static_assert(std::is_signed_v<std::atomic_signed_lock_free::value_type>);
+ static_assert(std::is_integral_v<std::atomic_signed_lock_free::value_type>);
+
test<std::atomic_unsigned_lock_free::value_type>();
+ static_assert(std::is_unsigned_v<std::atomic_unsigned_lock_free::value_type>);
+ static_assert(std::is_integral_v<std::atomic_unsigned_lock_free::value_type>);
/*
test<std::shared_ptr<int>>();
*/
More information about the libcxx-commits
mailing list