Skip to content

Commit f0d6bbf

Browse files
committed
Update the LockFreeStatus enum to support C++03.
Which was a royal pain.
1 parent 1bfc10f commit f0d6bbf

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

libcxx/test/std/atomics/atomics.ref/is_always_lock_free.pass.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
template <typename T>
2424
void check_always_lock_free(std::atomic_ref<T> const& a) {
25-
if (is_lock_free_status_known<T>()) {
26-
constexpr LockFreeStatus known_status = get_known_atomic_lock_free_status<T>();
25+
using InfoT = LockFreeStatusInfo<T>;
26+
27+
if (InfoT::status_known) {
28+
constexpr LockFreeStatus known_status = InfoT::value;
2729

2830
static_assert(std::atomic_ref<T>::is_always_lock_free == (known_status == LockFreeStatus::always),
2931
"is_always_lock_free is inconsistent with known lock-free status");

libcxx/test/support/atomic_helpers.h

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,24 @@ constexpr bool msvc_is_lock_free_macro_value() {
4949
#else
5050
# error "Unknown compiler"
5151
#endif
52-
enum class LockFreeStatus { unknown = -1, never = 0, sometimes = 1, always = 2 };
53-
#define COMPARE_TYPES(T1, T2) (sizeof(T1) == sizeof(T2) && alignof(T1) >= alignof(T2))
52+
53+
// The entire LockFreeStatus/LockFreeStatusEnum/LockFreeStatusType exists entirely to work around the support
54+
// for C++03, which many of our atomic tests run under. This is a bit of a hack, but it's the best we can do.
55+
//
56+
// We could limit the testing involving these things to C++11 or greater? But test coverage in C++03 seems important too.
57+
#if TEST_STD_VER < 11
58+
struct LockFreeStatusEnum {
59+
enum LockFreeStatus { unknown = -1, never = 0, sometimes = 1, always = 2 };
60+
};
61+
typedef LockFreeStatusEnum::LockFreeStatus LockFreeStatus;
62+
#else
63+
enum class LockFreeStatus : int { unknown = -1, never = 0, sometimes = 1, always = 2 };
64+
#endif
65+
#define COMPARE_TYPES(T1, T2) (sizeof(T1) == sizeof(T2) && TEST_ALIGNOF(T1) >= TEST_ALIGNOF(T2))
5466

5567
template <class T>
56-
constexpr inline LockFreeStatus get_known_atomic_lock_free_status() {
57-
return LockFreeStatus{
68+
struct LockFreeStatusInfo {
69+
static const LockFreeStatus value = LockFreeStatus(
5870
COMPARE_TYPES(T, char)
5971
? TEST_ATOMIC_CHAR_LOCK_FREE
6072
: (COMPARE_TYPES(T, short)
@@ -65,20 +77,23 @@ constexpr inline LockFreeStatus get_known_atomic_lock_free_status() {
6577
? TEST_ATOMIC_LONG_LOCK_FREE
6678
: (COMPARE_TYPES(T, long long)
6779
? TEST_ATOMIC_LLONG_LOCK_FREE
68-
: (COMPARE_TYPES(T, void*) ? TEST_ATOMIC_POINTER_LOCK_FREE : -1)))))};
69-
}
80+
: (COMPARE_TYPES(T, void*) ? TEST_ATOMIC_POINTER_LOCK_FREE : -1))))));
7081

71-
template <class T>
72-
constexpr bool is_lock_free_status_known() {
73-
return get_known_atomic_lock_free_status<T>() != LockFreeStatus::unknown;
74-
}
82+
static const bool status_known = value != LockFreeStatus::unknown;
83+
};
7584

76-
static_assert(is_lock_free_status_known<char>(), "");
77-
static_assert(is_lock_free_status_known<short>(), "");
78-
static_assert(is_lock_free_status_known<int>(), "");
79-
static_assert(is_lock_free_status_known<long>(), "");
80-
static_assert(is_lock_free_status_known<long long>(), "");
81-
static_assert(is_lock_free_status_known<void*>(), "");
85+
static_assert(LockFreeStatusInfo<char>::status_known, "");
86+
static_assert(LockFreeStatusInfo<short>::status_known, "");
87+
static_assert(LockFreeStatusInfo<int>::status_known, "");
88+
static_assert(LockFreeStatusInfo<long>::status_known, "");
89+
static_assert(LockFreeStatusInfo<long long>::status_known, "");
90+
static_assert(LockFreeStatusInfo<void*>::status_known, "");
91+
92+
// I think these are always supposed to be lock free, and it's worth trying to hardcode expected values.
93+
static_assert(LockFreeStatusInfo<char>::value == LockFreeStatus::always, "");
94+
static_assert(LockFreeStatusInfo<short>::value == LockFreeStatus::always, "");
95+
static_assert(LockFreeStatusInfo<int>::value == LockFreeStatus::always,
96+
""); // This one may not always be lock free, but we'll let the CI decide.
8297

8398
// These macros are somewhat suprising to use, since they take the values 0, 1, or 2.
8499
// To make the tests clearer, get rid of them in preference of AtomicInfo.

0 commit comments

Comments
 (0)