C++ Logo


Advanced search

Re: Synchronization of atomic notify and wait

From: Nate Eldredge <nate_at_[hidden]>
Date: Sun, 24 Jul 2022 17:29:23 -0700 (PDT)
On Thu, 21 Jul 2022, language.lawyer--- via Std-Discussion wrote:

> On 21/07/2022 04:01, Thiago Macieira via Std-Discussion wrote:
>> On Wednesday, 20 July 2022 07:39:53 PDT language.lawyer--- via
>> Std-Discussion
>> wrote:
>>>> You should understand the notify() as a non-value modification.
>>> You mean, it participates in the modification order of the atomic object?
>> Yes.
> I don't think I've ever seen something other than side-effects writing some
> value participating in the modification order.

I agree that it really seems like a stretch. The idea of x.notify() being
a "modification" that cannot affect the value of the atomic object x is
quite counter-intuitive. Moreover, in real machine implementations, I
would think that notify must be implemented at some level as a
modification to a *different* atomic object somewhere in the system. It
might be a hidden member of the std::atomic<T> object x, but for lock-free
types, it's more likely somewhere else, e.g. a "runnable" flag on
thread-safe wait queue in the library or the kernel, located by hashing
the address of x.

Of course in principle the C++ standard is free to define the required
observable behavior via any abstractions they wish, and leave it to the
implementors to sort out how to make it happen, but usually there's some
attempt to relate it to the functionality of actual systems and hardware.

Another concern is that if we want to use this interpretation to prove
that the post-unblock load sees the new value, I think we have to do so by
invoking read-read coherence (https://eel.is/c++draft/intro.races#16):

"If a value computation A of an atomic object M happens before a value
computation B of M, and A takes its value from a side effect X on M, then
the value computed by B shall either be the value stored by X or the value
stored by a side effect Y on M, where Y follows X in the modification
order of M."

So we have to take X to be the notify, A to be the unblock, and B to be
the post-unblock load. If it's strange to call the notify() a
"modification", it seems even stranger to call the unblock a "value
computation", since as you say the notify/wait has nothing to do with the
value of M. And the conclusion is that B computes the value "stored by"
the notify X, which in fact didn't store any value at all; so we have to
understand this as meaning the *preceding* side effect in the modification
order, i.e. the actual store.

If the committee intended this IMHO contorted interpretation, I wish they
would at least give us an explanatory footnote.

Nate Eldredge

Received on 2022-07-25 00:29:27