C++ Logo

std-proposals

Advanced search

Re: [std-proposals] atomic_compare_exchange_and_notify

From: Ryan P. Nicholl <rnicholl_at_[hidden]>
Date: Thu, 15 Jan 2026 20:11:59 +0000
> If you're having in mind a specific usage scenario involving std::latch,
where one of the waiters destroys the latch as soon as it wakes up, then
that would be an error of the user of std::latch.

The standard explicitly says this is allowed and well defined behavior.



--
Ryan P. Nicholl
Tel: (678)-358-7765
On Wednesday, January 14th, 2026 at 13:00, Andrey Semashev via Std-Proposals <std-proposals_at_[hidden]> wrote:
> On 14 Jan 2026 03:55, Ryan P. Nicholl via Std-Proposals 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.
> 
> 
> I'm not sure what the destructor of the atomic has to do with
> count_down. Assuming std::latch implementation is using std::atomic
> internally (which is not the only possible implementation), I don't see
> why count_down would ever destroy the atomic.
> 
> If you're having in mind a specific usage scenario involving std::latch,
> where one of the waiters destroys the latch as soon as it wakes up, then
> that would be an error of the user of std::latch.
> 
> > 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.
> > 
> > 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.
> 
> 
> Aside from the issue with the motivating example with std::latch,
> blessing only compare_exchange but not other modifying operations seem
> unnecessarily specific.
> 
> Note that it is generally impossible to make the modifying operation and
> the notifying operation atomic with the currently available futex-like
> system APIs. For a lock-free atomic, the modifying operation is
> typically one or few instructions that are distinct from a notifying
> syscall, and it is always possible that a blocked thread wakes up and
> destroys the atomic after the modifying operation has completed but
> before the notifying syscall has started. Note that "destroying" may not
> be limited to just C++ object model but also include e.g. unmapping
> memory location where the atomic was placed.
> 
> Even if you move the modifying operation inside the notifying syscall,
> under the lock that presumably protects the in-kernel list of waiters,
> that wouldn't help because a thread calling a wait may observe the
> modified value of the atomic before blocking and return immediately and
> destroy the atomic.
> 
> So the proposed operation doesn't really solve anything. The only thing
> that you could ask for is to bless notifying operations by saying they
> don't access the atomic and don't need a valid object at its location.
> Or not say it (the status quo), which means users must ensure the atomic
> object exists at all times while its operations are called. For the
> std::latch example, this means users must not destroy it until all
> waiters and callers of count_down have returned from the respective
> methods (e.g. by using std::shared_ptrstd::latch).
> 
> 
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2026-01-15 20:12:07