C++ Logo

std-proposals

Advanced search

Re: [std-proposals] atomic_compare_exchange_and_notify

From: Ryan P. Nicholl <rnicholl_at_[hidden]>
Date: Wed, 14 Jan 2026 20:10:39 +0000
When I say it's not possible to implement, what I mean is not that it can't be implemented, but rather that it can't be implemented using the C++ standard library without UB.

libc++ implements std::latch without any issue, so this clearly is possible to implement correctly.

However, libc++ implementation of std::latch is relying on something that the C++ standard library doesn't promise, namely `void __cxx_atomic_notify_all(void const volatile*)` in libc++ doesn't seem to require that the atomic object actually exist at that address. However, notify_all from C++ library doesn't give any such guarantee per standard, even if it works in libc++. Also, __atomic_contention_address could interact with atomic lifetime somehow if the implementation wanted to.

Since this is clearly implementable using the existing libc++ implementation as an example, I think it should be added to the standard if possible.

Really, all I need is a promise that I can notify an address which the atomic object might already be destroyed, that could also be a DR on existing C++ standards if it was permitted for the existing freestanding notify functions. However, I'm not sure if that could break any "clever" implementations of atomic. So my inclination would be adding atomic_compare_exchange_and_notify_* which is not required to be supported for types which are not lock-free.

--
Ryan P. Nicholl
Tel: (678)-358-7765
On Wednesday, January 14th, 2026 at 03:08, Jonathan Wakely <cxx_at_[hidden]> wrote:
> On Wed, 14 Jan 2026, 00:55 Ryan P. Nicholl via Std-Proposals, <std-proposals_at_[hidden]> wrote:
>
>> It has come to my attention that it isn't possible to implement data structures like std::latch or a uselock using the C++ atomic library without undefined behavior.
>>
>> Namely, std::latch guarantees that count_down doesn't cause a race even if there are waiters, this isn't possible to implement on the abstract machine unless the notification can be safely executed atomically with the value set. Ordinary notify_one has undefined behavior if it races with the destructor of the atomic object.
>
> That doesn't mean it isn't possible to implement. It means you have to be careful how you use it.
>
> Most types don't guarantee that you can destroy them while another thread is still using them, this isn't specific to std::latch. I think "it isn't possible to implement" is framing this completely wrong.
>
> It's also not true, you could implement it with a std::mutex and a std::condition_variable if you want to guarantee that waiters do not wake before a notify is complete.
>
>> Of course, it's possible to implement std::latch using things like SYS_futex, so this isn't impossible to implement per se, only impossible to implement using the C++ standard library without relying on undefined behavior.
>
> It's possible using FUTEX_WAKE_OP, but what about non-linux platforms?
>
>> I would propose adding atomic_compare_exchange_and_notify. This would have the same behavior as atomic compare_exchange followed by notify, except that it doesn't cause undefined behavior if a waiter unblocks on the new value and destroys the atomic, which could race with notify.
>
> How would that work for std::atomic<long long> which doesn't use a futex directly?
> I definitely think it would be nice to have a C++ type that exposes futex functionality directly with no additional overhead, but std::atomic is not that type.

Received on 2026-01-14 20:10:52