Skip to content

Commit 156439f

Browse files
refactor: Add and use atomic_ref_compatible checks for concurrency handlers
1 parent 168fcef commit 156439f

1 file changed

Lines changed: 33 additions & 4 deletions

File tree

src/policy/impl.cppm

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,28 @@ using concurrency = concurrency::none;
136136

137137
namespace details {
138138

139+
template <typename T, bool = std::is_trivially_copyable_v<T>>
140+
struct atomic_ref_alignment_compatible : std::false_type {};
141+
142+
template <typename T>
143+
struct atomic_ref_alignment_compatible<T, true>
144+
: std::bool_constant<(alignof(T) >=
145+
std::atomic_ref<T>::required_alignment)> {};
146+
147+
template <typename T>
148+
inline constexpr bool atomic_ref_compatible_v =
149+
atomic_ref_alignment_compatible<T>::value;
150+
151+
template <typename T> constexpr void assert_atomic_ref_compatible() {
152+
static_assert(std::is_trivially_copyable_v<T>,
153+
"concurrency::handler atomic access requires trivially "
154+
"copyable CommonRep");
155+
static_assert(
156+
atomic_ref_alignment_compatible<T>::value,
157+
"concurrency::handler atomic access requires alignof(CommonRep) to "
158+
"satisfy std::atomic_ref<CommonRep>::required_alignment");
159+
}
160+
139161
template <typename OpTag>
140162
inline constexpr bool is_arithmetic_operation_v =
141163
operations::op_has_capability_v<OpTag, operations::capability::arithmetic>;
@@ -150,6 +172,7 @@ inline constexpr bool rejects_arithmetic_for_boolean_or_character_v =
150172

151173
template <typename T>
152174
auto atomic_ref_load(T const &value, std::memory_order order) noexcept -> T {
175+
assert_atomic_ref_compatible<T>();
153176
// libc++ rejects std::atomic_ref<const T>; load through a non-mutating view.
154177
auto &mutable_value = const_cast<T &>(value);
155178
std::atomic_ref<T> ref(mutable_value);
@@ -295,7 +318,7 @@ struct concurrency::handler<concurrency::fenced_seq_cst, OpTag, CommonRep,
295318
template <typename CommonRep, typename ErrorPayload>
296319
struct concurrency::handler<concurrency::fenced, void, CommonRep,
297320
ErrorPayload> {
298-
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
321+
static constexpr bool enabled = details::atomic_ref_compatible_v<CommonRep>;
299322
using injection_type = concurrency::injection;
300323
using result_type = std::expected<CommonRep, ErrorPayload>;
301324

@@ -304,12 +327,14 @@ struct concurrency::handler<concurrency::fenced, void, CommonRep,
304327
}
305328

306329
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
330+
details::assert_atomic_ref_compatible<CommonRep>();
307331
std::atomic_ref<CommonRep> ref(value);
308332
ref.store(desired, std::memory_order_seq_cst);
309333
}
310334

311335
static auto compare_exchange(CommonRep &value, CommonRep &expected,
312336
CommonRep desired) noexcept -> bool {
337+
details::assert_atomic_ref_compatible<CommonRep>();
313338
std::atomic_ref<CommonRep> ref(value);
314339
return ref.compare_exchange_strong(expected, desired,
315340
std::memory_order_seq_cst,
@@ -320,7 +345,7 @@ struct concurrency::handler<concurrency::fenced, void, CommonRep,
320345
template <typename CommonRep, typename ErrorPayload>
321346
struct concurrency::handler<concurrency::fenced_relaxed, void, CommonRep,
322347
ErrorPayload> {
323-
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
348+
static constexpr bool enabled = details::atomic_ref_compatible_v<CommonRep>;
324349
using injection_type = concurrency::injection;
325350
using result_type = std::expected<CommonRep, ErrorPayload>;
326351

@@ -329,12 +354,14 @@ struct concurrency::handler<concurrency::fenced_relaxed, void, CommonRep,
329354
}
330355

331356
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
357+
details::assert_atomic_ref_compatible<CommonRep>();
332358
std::atomic_ref<CommonRep> ref(value);
333359
ref.store(desired, std::memory_order_relaxed);
334360
}
335361

336362
static auto compare_exchange(CommonRep &value, CommonRep &expected,
337363
CommonRep desired) noexcept -> bool {
364+
details::assert_atomic_ref_compatible<CommonRep>();
338365
std::atomic_ref<CommonRep> ref(value);
339366
return ref.compare_exchange_strong(expected, desired,
340367
std::memory_order_relaxed,
@@ -345,7 +372,7 @@ struct concurrency::handler<concurrency::fenced_relaxed, void, CommonRep,
345372
template <typename CommonRep, typename ErrorPayload>
346373
struct concurrency::handler<concurrency::fenced_acq_rel, void, CommonRep,
347374
ErrorPayload> {
348-
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
375+
static constexpr bool enabled = details::atomic_ref_compatible_v<CommonRep>;
349376
using injection_type = concurrency::injection;
350377
using result_type = std::expected<CommonRep, ErrorPayload>;
351378

@@ -354,12 +381,14 @@ struct concurrency::handler<concurrency::fenced_acq_rel, void, CommonRep,
354381
}
355382

356383
static auto store(CommonRep &value, CommonRep desired) noexcept -> void {
384+
details::assert_atomic_ref_compatible<CommonRep>();
357385
std::atomic_ref<CommonRep> ref(value);
358386
ref.store(desired, std::memory_order_release);
359387
}
360388

361389
static auto compare_exchange(CommonRep &value, CommonRep &expected,
362390
CommonRep desired) noexcept -> bool {
391+
details::assert_atomic_ref_compatible<CommonRep>();
363392
std::atomic_ref<CommonRep> ref(value);
364393
return ref.compare_exchange_strong(expected, desired,
365394
std::memory_order_acq_rel,
@@ -370,7 +399,7 @@ struct concurrency::handler<concurrency::fenced_acq_rel, void, CommonRep,
370399
template <typename CommonRep, typename ErrorPayload>
371400
struct concurrency::handler<concurrency::fenced_seq_cst, void, CommonRep,
372401
ErrorPayload> {
373-
static constexpr bool enabled = std::is_trivially_copyable_v<CommonRep>;
402+
static constexpr bool enabled = details::atomic_ref_compatible_v<CommonRep>;
374403
using injection_type = concurrency::injection;
375404
using result_type = std::expected<CommonRep, ErrorPayload>;
376405

0 commit comments

Comments
 (0)