Use C++20 atomics for packed bit-vector helpers

Merged
AD
1mo ago
+121-63

Use C++20 std::atomic_ref for packed bit-vector words and 64-bit differential counters. The bit-vector helpers accept std::memory_order directly, so the compiler-order conversion switch is removed. Keep the existing builtin operations for packed 8/16/32-bit counters; all counter call sites already use relaxed ordering, so their unused ordering parameter is removed.

A small load-only wrapper works around libc++ versions that cannot instantiate atomic_ref::load. The new header uses a project-prefixed guard. Extend concurrent coverage to both setting and clearing bits.

Validation: GCC, Clang and Clang/libc++ concurrency checks pass, as does UBSan. Before/after instruction lists match for 11 bit operations on each compiler (33 comparisons). Targeted translation units and the committed regression test pass. Full CI will rerun after restacking.

Stacked on #649. Review/merge order: #647 → #648 → #649 → #646 → #644.


Summary by cubic

Switches the packed bit-vector atomic helpers from compiler builtins and integer memory orders to std::atomic_ref with std::memory_order, since the implicit conversion between them breaks under C++20. A new utils::atomic_load wrapper covers const access, which libc++'s atomic_ref<const T> cannot instantiate.

  • Callers using the atomic flag now pass std::memory_order_*; external callers passing __ATOMIC_* constants must switch to the standard enum.
  • atomic_fetch and atomic_fetch_and_add dropped their memory-order parameter and are always relaxed; 64-bit counters use atomic_ref while 8/16/32-bit counters keep the builtin operations.
  • Adds a concurrent test verifying each bit transitions exactly once across five memory orders, for both setting and clearing.