[libcxx-commits] [libcxx] [libcxx] P0718R2: Implementation of std::atomic<shared_ptr<T>> and std::atomic<weak_ptr<T>> (PR #194215)

Vladislav Semykin via libcxx-commits libcxx-commits at lists.llvm.org
Wed Apr 29 09:18:32 PDT 2026


ViNN280801 wrote:

@huixie90, I analyzed some cases:

Bare DWCAS (`std::atomic<__uint128_t>` / `cmpxchg16b`) is necessary but not sufficient - `load()` still has a **refcount liveness window**:

```cpp
// Naive - contains UAF:
pair = storage.load();  // (1) read {ptr, ctrl}
ctrl->add_shared();     // (2) UAF: another thread may have freed ctrl between (1) and (2)
```

## Three mechanisms close this window

### A. Split refcount (Williams / Just::Thread)

Pack local refcount into the 128-bit word:

```cpp
// 128-bit: [ ctrl_ptr (64) | local_ref (32) | version (32) ]
loop:
    old = storage.load()
    new = old with local_ref++
    if DWCAS(storage, old, new): return make_shared(ptr, ctrl)
    // ctrl cannot be freed while local_ref > 0
```
Implementable now, no external deps. Reference: https://github.com/anthonywilliams/atomic_shared_ptr

## B. Hazard pointer (Anderson)

Portable, but requires P2530R3 which is not yet in libc++. (I can make attempt to implement it as I mentioned above).

## C. DWCAS aspiration (Big Atomics, PPoPP 2025)

Version tag against ABA, speculative increment with rollback. Reference: https://arxiv.org/abs/2501.07503
Which approach does the team prefer for the fast path on x86-64 / AArch64 LSE?

https://github.com/llvm/llvm-project/pull/194215


More information about the libcxx-commits mailing list