@@ -136,6 +136,28 @@ using concurrency = concurrency::none;
136136
137137namespace 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+
139161template <typename OpTag>
140162inline 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
151173template <typename T>
152174auto 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,
295318template <typename CommonRep, typename ErrorPayload>
296319struct 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,
320345template <typename CommonRep, typename ErrorPayload>
321346struct 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,
345372template <typename CommonRep, typename ErrorPayload>
346373struct 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,
370399template <typename CommonRep, typename ErrorPayload>
371400struct 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