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 22:33:11 +0000
It seems silly to not support adding this behavior.

First, C++ is supposed to be "Zero overhead". If I cannot implement a customized mutex with std::atomic, it has mostly failed on that point.

I expect to be able to implement a mutex, the same way I can implement my own vector type to customize the behavior.

> I would not support such a change.

Any reasoning other than no? All implementations already do this, seems reasonable to me to extend what can be done with well defined C++. I'm not sure if there are any implementations that don't​ allow this, but I guess one not allowing it would be grounds to avoid doing so. But I think we should DR this if all implementations allow it, and all the ones I've checked do.

It's also kind of unlikely that an implementation will not​ allow notify on destroyed object, since that operation is required to implement both pthread_mutex and std::mutex in a standard compliant way.

It is theoretically possible that a platform only uses that implementation for std::mutex and uses a different implementation for non-mutex notify, but I am not aware of any such implementations existing.

--
Ryan P. Nicholl
Tel: (678)-358-7765
On Wednesday, January 14th, 2026 at 13:47, Jonathan Wakely <cxx_at_[hidden]> wrote:
> On Wed, 14 Jan 2026 at 20:42, Ryan P. Nicholl <rnicholl_at_[hidden]> wrote:
>
>>> 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.
>>
>> std::mutex and condition_variable can't be implemented using only the guarantees in the standard provided by std::atomic either.
>
> They don't need to be, because they're provided by the standard library.
>
>> I'm not sure how concerning this is in practice, given pthreads (which is usually used to implement mutex) says as follows:
>>
>>> The pthread_mutex_destroy() function shall destroy the mutex object referenced by mutex; the mutex object becomes, in effect, uninitialized. An implementation may cause pthread_mutex_destroy() to set the object referenced by mutex to an invalid value. A destroyed mutex object can be reinitialized using pthread_mutex_init(); the results of otherwise referencing the object after it has been destroyed are undefined.
>>>
>>> It shall be safe to destroy an initialized mutex that is unlocked. Attempting to destroy a locked mutex results in undefined behavior.
>>
>> Seems the pthread mutex implementation guarantees this is safe, but the C++ standard, as best I can tell, does not provide a way to implement either behavior using std::atomic.
>
> I don't read it that way. In the abstract machine there is no time between the "unlock" and the conceptual "notify" that happens to inform other threads that they can lock it. It's not like a std::atomic.
>
> If the thread that unlocks the mutex also destroys it, then you know the unlock is sequenced before the destroy. If those two operations happen in separate threads, you need external synchronization to ensure that the unlock happens before the destroy (otherwise you can't know that the destroy doesn't happen while the mutex is still locked, which would be UB). Either way, the return from pthread_mutex_unlock happens before the pthread_mutex_destroy, so this isn't comparable to the case you're describing where you want to destroy an atomic concurrently with a notify on that atomic (which is just user error as Andrey said in another reply - don't do that).
>
>> Looking at MUSL, it seems like it's using a very similar strategy to libc++ for implementing pthread_mutex_unlock();
>>
>> LeaveCriticalSection has the same behavior.
>>
>> It looks like all major implementations use this type of "mutate and notify" operation internally, but the standard library doesn't expose any way to do this which is not relying on what seems like UB.
>> If there is something somewhere which defines this as working, I'm interested to know what it would be.
>>
>> I do not think you can (legally) implement std::mutex using std::atomic in a way that doesn't rely on these behaviors.
>
> The standard doesn't need to provide a way to implement std::mutex at all.
>
>> Alternative: publish a DR that clarifies that "atomic_notify_*" functions are well defined and do not cause a race even if the object no longer exists at the pointed address. I think this will work for recent Windows STL, libc++, Glibc, and MUSL, at least for most types. I haven't checked other implementations.
>
> I would not support such a change.

Received on 2026-01-14 22:33:18