24
24
#include " test_helper.h"
25
25
#include " test_macros.h"
26
26
27
- template <typename T>
27
+ template <typename T, typename U>
28
+ concept has_compare_exchange_strong_1 =
29
+ requires { std::declval<T>().compare_exchange_strong (std::declval<U&>(), std::declval<U>()); };
30
+ template <typename T, typename U>
31
+ concept has_compare_exchange_strong_2 = requires {
32
+ std::declval<T>().compare_exchange_strong (std::declval<U&>(), std::declval<U>(), std::declval<std::memory_order>());
33
+ };
34
+ template <typename T, typename U>
35
+ concept has_compare_exchange_strong_3 = requires {
36
+ std::declval<T>().compare_exchange_strong (
37
+ std::declval<U&>(), std::declval<U>(), std::declval<std::memory_order>(), std::declval<std::memory_order>());
38
+ };
39
+
40
+ template <typename T, typename U>
41
+ concept has_compare_exchange_strong =
42
+ has_compare_exchange_strong_1<T, U> && has_compare_exchange_strong_2<T, U> && has_compare_exchange_strong_3<T, U>;
43
+
44
+ template <typename T, typename U>
45
+ concept does_not_have_compare_exchange_strong =
46
+ !has_compare_exchange_strong_1<T, U> && !has_compare_exchange_strong_2<T, U> &&
47
+ !has_compare_exchange_strong_3<T, U>;
48
+
49
+ template <typename U>
28
50
struct TestCompareExchangeStrong {
29
51
void operator ()() const {
52
+ static_assert (has_compare_exchange_strong<std::atomic_ref<U>, U>);
53
+ do_test<U>();
54
+ do_test_atomic<U>();
55
+ static_assert (does_not_have_compare_exchange_strong<std::atomic_ref<U const >, U>);
56
+ if constexpr (std::atomic_ref<U>::is_always_lock_free) {
57
+ static_assert (has_compare_exchange_strong<std::atomic_ref<U volatile >, U>);
58
+ do_test<U volatile >();
59
+ do_test_atomic<U volatile >();
60
+ static_assert (does_not_have_compare_exchange_strong<std::atomic_ref<U const volatile >, U>);
61
+ }
62
+ }
63
+
64
+ template <typename T>
65
+ void do_test () const {
30
66
{
31
67
T x (T (1 ));
32
68
std::atomic_ref<T> const a (x);
33
69
34
- T t (T (1 ));
70
+ std:: remove_cv_t <T> t (T (1 ));
35
71
std::same_as<bool > decltype (auto ) y = a.compare_exchange_strong (t, T (2 ));
36
72
assert (y == true );
37
- assert (a == T (2 ));
38
- assert (t == T (1 ));
73
+ assert (a == std:: remove_cv_t <T> (2 ));
74
+ assert (t == std:: remove_cv_t <T> (1 ));
39
75
y = a.compare_exchange_strong (t, T (3 ));
40
76
assert (y == false );
41
- assert (a == T (2 ));
42
- assert (t == T (2 ));
77
+ assert (a == std:: remove_cv_t <T> (2 ));
78
+ assert (t == std:: remove_cv_t <T> (2 ));
43
79
44
80
ASSERT_NOEXCEPT (a.compare_exchange_strong (t, T (2 )));
45
81
}
46
82
{
47
83
T x (T (1 ));
48
84
std::atomic_ref<T> const a (x);
49
85
50
- T t (T (1 ));
86
+ std:: remove_cv_t <T> t (T (1 ));
51
87
std::same_as<bool > decltype (auto ) y = a.compare_exchange_strong (t, T (2 ), std::memory_order_seq_cst);
52
88
assert (y == true );
53
- assert (a == T (2 ));
54
- assert (t == T (1 ));
89
+ assert (a == std:: remove_cv_t <T> (2 ));
90
+ assert (t == std:: remove_cv_t <T> (1 ));
55
91
y = a.compare_exchange_strong (t, T (3 ), std::memory_order_seq_cst);
56
92
assert (y == false );
57
- assert (a == T (2 ));
58
- assert (t == T (2 ));
93
+ assert (a == std:: remove_cv_t <T> (2 ));
94
+ assert (t == std:: remove_cv_t <T> (2 ));
59
95
60
96
ASSERT_NOEXCEPT (a.compare_exchange_strong (t, T (2 ), std::memory_order_seq_cst));
61
97
}
62
98
{
63
99
T x (T (1 ));
64
100
std::atomic_ref<T> const a (x);
65
101
66
- T t (T (1 ));
102
+ std:: remove_cv_t <T> t (T (1 ));
67
103
std::same_as<bool > decltype (auto ) y =
68
104
a.compare_exchange_strong (t, T (2 ), std::memory_order_release, std::memory_order_relaxed);
69
105
assert (y == true );
70
- assert (a == T (2 ));
71
- assert (t == T (1 ));
106
+ assert (a == std:: remove_cv_t <T> (2 ));
107
+ assert (t == std:: remove_cv_t <T> (1 ));
72
108
y = a.compare_exchange_strong (t, T (3 ), std::memory_order_release, std::memory_order_relaxed);
73
109
assert (y == false );
74
- assert (a == T (2 ));
75
- assert (t == T (2 ));
110
+ assert (a == std:: remove_cv_t <T> (2 ));
111
+ assert (t == std:: remove_cv_t <T> (2 ));
76
112
77
113
ASSERT_NOEXCEPT (a.compare_exchange_strong (t, T (2 ), std::memory_order_release, std::memory_order_relaxed));
78
114
}
115
+ }
79
116
117
+ template <typename T>
118
+ void do_test_atomic () const {
80
119
// success memory_order::release
81
120
{
82
- auto store = [](std::atomic_ref<T> const & x, T old_val, T new_val) {
83
- auto r = x.compare_exchange_strong (old_val, new_val, std::memory_order::release, std::memory_order::relaxed);
121
+ auto store = [](std::atomic_ref<T> const & x, T const & old_val, T const & new_val) {
122
+ auto r = x.compare_exchange_strong (
123
+ const_cast <std::remove_cv_t <T>&>(old_val),
124
+ const_cast <std::remove_cv_t <T> const &>(new_val),
125
+ std::memory_order::release,
126
+ std::memory_order::relaxed);
84
127
assert (r);
85
128
};
86
129
87
130
auto load = [](std::atomic_ref<T> const & x) { return x.load (std::memory_order::acquire); };
88
131
test_acquire_release<T>(store, load);
89
-
90
- auto store_one_arg = [](std::atomic_ref<T> const & x, T old_val, T new_val) {
91
- auto r = x.compare_exchange_strong (old_val, new_val, std::memory_order::release);
132
+ auto store_one_arg = [](std::atomic_ref<T> const & x, T const & old_val, T const & new_val) {
133
+ auto r = x.compare_exchange_strong (
134
+ const_cast <std::remove_cv_t <T>&>(old_val),
135
+ const_cast <std::remove_cv_t <T> const &>(new_val),
136
+ std::memory_order::release);
92
137
assert (r);
93
138
};
94
139
test_acquire_release<T>(store_one_arg, load);
95
140
}
96
141
97
142
// success memory_order::acquire
98
143
{
99
- auto store = [](std::atomic_ref<T> const & x, T, T new_val) { x.store (new_val, std::memory_order::release); };
144
+ auto store = [](std::atomic_ref<T> const & x, T const &, T const & new_val) {
145
+ x.store (const_cast <std::remove_cv_t <T> const &>(new_val), std::memory_order::release);
146
+ };
100
147
101
148
auto load = [](std::atomic_ref<T> const & x) {
102
149
auto val = x.load (std::memory_order::relaxed);
@@ -117,8 +164,12 @@ struct TestCompareExchangeStrong {
117
164
118
165
// success memory_order::acq_rel
119
166
{
120
- auto store = [](std::atomic_ref<T> const & x, T old_val, T new_val) {
121
- auto r = x.compare_exchange_strong (old_val, new_val, std::memory_order::acq_rel, std::memory_order::relaxed);
167
+ auto store = [](std::atomic_ref<T> const & x, T const & old_val, T const & new_val) {
168
+ auto r = x.compare_exchange_strong (
169
+ const_cast <std::remove_cv_t <T>&>(old_val),
170
+ const_cast <std::remove_cv_t <T> const &>(new_val),
171
+ std::memory_order::acq_rel,
172
+ std::memory_order::relaxed);
122
173
assert (r);
123
174
};
124
175
auto load = [](std::atomic_ref<T> const & x) {
@@ -129,8 +180,11 @@ struct TestCompareExchangeStrong {
129
180
};
130
181
test_acquire_release<T>(store, load);
131
182
132
- auto store_one_arg = [](std::atomic_ref<T> const & x, T old_val, T new_val) {
133
- auto r = x.compare_exchange_strong (old_val, new_val, std::memory_order::acq_rel);
183
+ auto store_one_arg = [](std::atomic_ref<T> const & x, T const & old_val, T const & new_val) {
184
+ auto r = x.compare_exchange_strong (
185
+ const_cast <std::remove_cv_t <T>&>(old_val),
186
+ const_cast <std::remove_cv_t <T> const &>(new_val),
187
+ std::memory_order::acq_rel);
134
188
assert (r);
135
189
};
136
190
auto load_one_arg = [](std::atomic_ref<T> const & x) {
@@ -144,8 +198,12 @@ struct TestCompareExchangeStrong {
144
198
145
199
// success memory_order::seq_cst
146
200
{
147
- auto store = [](std::atomic_ref<T> const & x, T old_val, T new_val) {
148
- auto r = x.compare_exchange_strong (old_val, new_val, std::memory_order::seq_cst, std::memory_order::relaxed);
201
+ auto store = [](std::atomic_ref<T> const & x, T const & old_val, T const & new_val) {
202
+ auto r = x.compare_exchange_strong (
203
+ const_cast <std::remove_cv_t <T>&>(old_val),
204
+ const_cast <std::remove_cv_t <T> const &>(new_val),
205
+ std::memory_order::seq_cst,
206
+ std::memory_order::relaxed);
149
207
assert (r);
150
208
};
151
209
auto load = [](std::atomic_ref<T> const & x) {
@@ -156,8 +214,11 @@ struct TestCompareExchangeStrong {
156
214
};
157
215
test_seq_cst<T>(store, load);
158
216
159
- auto store_one_arg = [](std::atomic_ref<T> const & x, T old_val, T new_val) {
160
- auto r = x.compare_exchange_strong (old_val, new_val, std::memory_order::seq_cst);
217
+ auto store_one_arg = [](std::atomic_ref<T> const & x, T const & old_val, T const & new_val) {
218
+ auto r = x.compare_exchange_strong (
219
+ const_cast <std::remove_cv_t <T>&>(old_val),
220
+ const_cast <std::remove_cv_t <T> const &>(new_val),
221
+ std::memory_order::seq_cst);
161
222
assert (r);
162
223
};
163
224
auto load_one_arg = [](std::atomic_ref<T> const & x) {
@@ -171,10 +232,12 @@ struct TestCompareExchangeStrong {
171
232
172
233
// failure memory_order::acquire
173
234
{
174
- auto store = [](std::atomic_ref<T> const & x, T, T new_val) { x.store (new_val, std::memory_order::release); };
175
- auto load = [](std::atomic_ref<T> const & x) {
235
+ auto store = [](std::atomic_ref<T> const & x, T const &, T const & new_val) {
236
+ x.store (const_cast <std::remove_cv_t <T> const &>(new_val), std::memory_order::release);
237
+ };
238
+ auto load = [](std::atomic_ref<T> const & x) {
176
239
auto result = x.load (std::memory_order::relaxed);
177
- T unexpected (T (255 ));
240
+ std:: remove_cv_t <T> unexpected (std:: remove_cv_t <T> (255 ));
178
241
bool r =
179
242
x.compare_exchange_strong (unexpected, unexpected, std::memory_order::relaxed, std::memory_order::acquire);
180
243
assert (!r);
@@ -184,7 +247,7 @@ struct TestCompareExchangeStrong {
184
247
185
248
auto load_one_arg = [](std::atomic_ref<T> const & x) {
186
249
auto result = x.load (std::memory_order::relaxed);
187
- T unexpected (T (255 ));
250
+ std:: remove_cv_t <T> unexpected (std:: remove_cv_t <T> (255 ));
188
251
bool r = x.compare_exchange_strong (unexpected, unexpected, std::memory_order::acquire);
189
252
assert (!r);
190
253
return result;
@@ -194,7 +257,7 @@ struct TestCompareExchangeStrong {
194
257
// acq_rel replaced by acquire
195
258
auto load_one_arg_acq_rel = [](std::atomic_ref<T> const & x) {
196
259
auto result = x.load (std::memory_order::relaxed);
197
- T unexpected (T (255 ));
260
+ std:: remove_cv_t <T> unexpected (std:: remove_cv_t <T> (255 ));
198
261
bool r = x.compare_exchange_strong (unexpected, unexpected, std::memory_order::acq_rel);
199
262
assert (!r);
200
263
return result;
@@ -204,10 +267,12 @@ struct TestCompareExchangeStrong {
204
267
205
268
// failure memory_order::seq_cst
206
269
{
207
- auto store = [](std::atomic_ref<T> const & x, T, T new_val) { x.store (new_val, std::memory_order::seq_cst); };
208
- auto load = [](std::atomic_ref<T> const & x) {
270
+ auto store = [](std::atomic_ref<T> const & x, T const &, T const & new_val) {
271
+ x.store (const_cast <std::remove_cv_t <T> const &>(new_val), std::memory_order::seq_cst);
272
+ };
273
+ auto load = [](std::atomic_ref<T> const & x) {
209
274
auto result = x.load (std::memory_order::relaxed);
210
- T unexpected (T (255 ));
275
+ std:: remove_cv_t <T> unexpected (std:: remove_cv_t <T> (255 ));
211
276
bool r =
212
277
x.compare_exchange_strong (unexpected, unexpected, std::memory_order::relaxed, std::memory_order::seq_cst);
213
278
assert (!r);
0 commit comments