[RFC] Implementing std::atomic<shared_ptr<T>> and std::atomic<weak_ptr<T>> (P0718R2) for libc++

Short Summary

This RFC proposes the implementation of P0718R2 (“Revising atomic_shared_ptr”) for libc++, which introduces std::atomic<std::shared_ptr<T>> and std::atomic<std::weak_ptr<T>> as mandated by C++20. A working implementation is available in PR #194215.

Motivation

std::atomic<std::shared_ptr<T>> and std::atomic<std::weak_ptr<T>> were adopted into the C++20 standard via P0718R2 (and later P2017R1) to allow for lock-free (or at least atomic) operations on shared pointers, which is essential for building concurrent data structures.

Currently, libc++ is the only major standard library implementation (compared to libstdc++ and MSVC STL) that lacks this feature. Instantiating std::atomic<shared_ptr<T>> in libc++ results in a hard static_assert because shared_ptr is not trivially copyable, which is contrary to the standard library requirements (the specialization is explicitly allowed).

Goals

  • implement the specializations for std::atomic as per [util.smartptr.atomic].
  • support C++20 and later standards.
  • ensure conformance with LWG 3661 (constinit support) and LWG 3893 (operator= from nullptr).
  • provide the wait/notify APIs introduced by P1135R6 for these types.

Open Questions and Future Directions

Lock-free implementation

While the standard permits a lock-based implementation, the original motivation for this feature was to enable lock-free data structures. There is interest in providing a lock-free (or hazard-pointer-based) path for platforms that support 16-byte CAS (x86-64 with CX16, AArch64 LSE).

  • Proposal: investigate a hybrid DWCAS (Double-Wide Compare-And-Swap) implementation using __uint128_t or compiler intrinsics for a future PR. This would require careful ABI compatibility planning if we change the layout later.
  • Question: does the community prefer to land this lock-based PR behind the -fexperimental-library flag to allow for future ABI-breaking improvements, or is a final lock-based ABI acceptable as a “Phase 1”?

AIX CI Timeouts

The stress test (atomic_shared_ptr_stress.pass.cpp) occasionally times out on AIX (64-bit) under high load (48 workers).

  • Question: is anyone with AIX experience able to assist in debugging or reviewing?

Hazard Pointer Integration

P2530R3 (Hazard Pointers) is a future C++26 feature. Could implementing it in libc++ provide a cleaner basis for a portable lock-free atomic<shared_ptr>?

This approach differs a lot from GCC and MSVC. As far as I understand, it’s supposed to be a next step compared to GCC’s approach. I would like to see normalized benchmarks comparing different approaches.

Regarding the hazard_ptr’s I’ve been working on, having atomic<shared_ptr> doesn’t seem to be necessary.
RFC for hazard_ptr’s