Skip to content

Commit 6f0c52e

Browse files
authored
[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
1 parent 5d73c7d commit 6f0c52e

File tree

3 files changed

+31
-28
lines changed

3 files changed

+31
-28
lines changed

libcxx/include/__atomic/aliases.h

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <__atomic/is_always_lock_free.h>
1616
#include <__config>
1717
#include <__type_traits/conditional.h>
18+
#include <__type_traits/make_unsigned.h>
1819
#include <cstddef>
1920
#include <cstdint>
2021
#include <cstdlib>
@@ -80,36 +81,30 @@ using atomic_ptrdiff_t = atomic<ptrdiff_t>;
8081
using atomic_intmax_t = atomic<intmax_t>;
8182
using atomic_uintmax_t = atomic<uintmax_t>;
8283

83-
// atomic_*_lock_free : prefer the contention type most highly, then the largest lock-free type
84+
// C++20 atomic_{signed,unsigned}_lock_free: prefer the contention type most highly, then the largest lock-free type
85+
#if _LIBCPP_STD_VER >= 20
86+
# if ATOMIC_LLONG_LOCK_FREE == 2
87+
using __largest_lock_free_type = long long;
88+
# elif ATOMIC_INT_LOCK_FREE == 2
89+
using __largest_lock_free_type = int;
90+
# elif ATOMIC_SHORT_LOCK_FREE == 2
91+
using __largest_lock_free_type = short;
92+
# elif ATOMIC_CHAR_LOCK_FREE == 2
93+
using __largest_lock_free_type = char;
94+
# else
95+
# define _LIBCPP_NO_LOCK_FREE_TYPES // There are no lockfree types (this can happen in freestanding)
96+
# endif
8497

85-
#if _LIBCPP_STD_VER >= 17
86-
# define _LIBCPP_CONTENTION_LOCK_FREE ::std::__libcpp_is_always_lock_free<__cxx_contention_t>::__value
87-
#else
88-
# define _LIBCPP_CONTENTION_LOCK_FREE false
89-
#endif
90-
91-
#if ATOMIC_LLONG_LOCK_FREE == 2
92-
using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, long long>;
93-
using __libcpp_unsigned_lock_free =
94-
__conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned long long>;
95-
#elif ATOMIC_INT_LOCK_FREE == 2
96-
using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, int>;
97-
using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned int>;
98-
#elif ATOMIC_SHORT_LOCK_FREE == 2
99-
using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, short>;
100-
using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned short>;
101-
#elif ATOMIC_CHAR_LOCK_FREE == 2
102-
using __libcpp_signed_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, char>;
103-
using __libcpp_unsigned_lock_free = __conditional_t<_LIBCPP_CONTENTION_LOCK_FREE, __cxx_contention_t, unsigned char>;
104-
#else
105-
// No signed/unsigned lock-free types
106-
# define _LIBCPP_NO_LOCK_FREE_TYPES
107-
#endif
98+
# ifndef _LIBCPP_NO_LOCK_FREE_TYPES
99+
using __contention_t_or_largest =
100+
__conditional_t<__libcpp_is_always_lock_free<__cxx_contention_t>::__value,
101+
__cxx_contention_t,
102+
__largest_lock_free_type>;
108103

109-
#if !defined(_LIBCPP_NO_LOCK_FREE_TYPES)
110-
using atomic_signed_lock_free = atomic<__libcpp_signed_lock_free>;
111-
using atomic_unsigned_lock_free = atomic<__libcpp_unsigned_lock_free>;
112-
#endif
104+
using atomic_signed_lock_free = atomic<__contention_t_or_largest>;
105+
using atomic_unsigned_lock_free = atomic<make_unsigned_t<__contention_t_or_largest>>;
106+
# endif // !_LIBCPP_NO_LOCK_FREE_TYPES
107+
#endif // C++20
113108

114109
_LIBCPP_END_NAMESPACE_STD
115110

libcxx/include/atomic

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,9 @@ typedef atomic<ptrdiff_t> atomic_ptrdiff_t;
514514
typedef atomic<intmax_t> atomic_intmax_t;
515515
typedef atomic<uintmax_t> atomic_uintmax_t;
516516
517+
typedef see-below atomic_signed_lock_free; // since C++20
518+
typedef see-below atomic_unsigned_lock_free; // since C++20
519+
517520
// flag type and operations
518521
519522
typedef struct atomic_flag

libcxx/test/std/atomics/types.pass.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,12 @@ int main(int, char**)
175175

176176
#if TEST_STD_VER >= 20
177177
test<std::atomic_signed_lock_free::value_type>();
178+
static_assert(std::is_signed_v<std::atomic_signed_lock_free::value_type>);
179+
static_assert(std::is_integral_v<std::atomic_signed_lock_free::value_type>);
180+
178181
test<std::atomic_unsigned_lock_free::value_type>();
182+
static_assert(std::is_unsigned_v<std::atomic_unsigned_lock_free::value_type>);
183+
static_assert(std::is_integral_v<std::atomic_unsigned_lock_free::value_type>);
179184
/*
180185
test<std::shared_ptr<int>>();
181186
*/

0 commit comments

Comments
 (0)