[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