C++ Logo

std-discussion

Advanced search

Re: Synchronization of atomic notify and wait

From: Marcin Jaczewski <marcinjaczewski86_at_[hidden]>
Date: Mon, 18 Jul 2022 23:11:06 +0200
pon., 18 lip 2022 o 22:27 Andrey Semashev via Std-Discussion
<std-discussion_at_[hidden]> napisał(a):
>
> On 7/18/22 22:57, Marcin Jaczewski wrote:
> > pon., 18 lip 2022 o 21:49 Andrey Semashev via Std-Discussion
> > <std-discussion_at_[hidden]> napisał(a):
> >>
> >> On 7/18/22 22:04, Nate Eldredge via Std-Discussion wrote:
> >>> On Mon, 18 Jul 2022, Marcin Jaczewski via Std-Discussion wrote:
> >>>
> >>>> To compare to `atomics.wait#4` we have:
> >>>> ```
> >>>> std::atomic<bool> b{false}; //EVENT X
> >>>>
> >>>> void thr1() {
> >>>> b.store(true, std::memory_order_relaxed); //EVENT Y
> >>>> b.notify_one(); //NOTIFY
> >>>> }
> >>>>
> >>>> int main() {
> >>>> std::thread t(thr1);
> >>>> b.wait(false); //BLOCK
> >>>> t.join();
> >>>> return 0;
> >>>> }
> >>>> ```
> >>>>
> >>>> "the atomic waiting operation has blocked after observing the result
> >>>> of X," -> this X happens before `main` start, and means should be
> >>>> visible for block operation.
> >>>>
> >>>> "X precedes Y in the modification order of M, and" -> again X happens
> >>>> before thread start
> >>>>
> >>>> "Y happens before the call to the atomic notifying operation." -> is
> >>>> line before notify
> >>>>
> >>>> For mea this is clear that the function should unblock there.
> >>>> Is This correct interpretation?
> >>>
> >>> I agree that, if the wait blocks at all, then it unblocks at least once.
> >>> That is not the issue. But after it unblocks, it reloads the value of b
> >>> to decide whether to return or to block again. The question is whether,
> >>> after unblocking in response to the notify, it might load the value
> >>> `false` and thus block again.
> >>
> >> How is this possible, under the current ordering rules?
> >
> > Because http://eel.is/c++draft/atomics.wait#4 requires this?
>
> I was asking the OP how was his theoretical scenario of reversed store
> and notify possible. Because I don't see how, according to the ordering
> rules mentioned so far in the discussion.
>
> > I understand this work the same as `memcpy` in context of object life time.
> > You can have a naive `memcpy` but you can't have the same behavior
> > that standard gives to the original.
> > This means you can't implement `wait` using current ordering rules but still
> > `std::wait` works fine because standard demand it to work.
>
> Obviously, wait can be implemented as there are real world
> implementations. The standard isn't written to demand something that is
> impossible to implement.

Yes, it is possible to implement but not in pure C++ as it could use
compiler intrinsics
or assembler. It could use code that have total ordering garatees or
use memory feces.

I grab random code with "wait" from:
https://github.com/llvm/llvm-project/blob/main/libcxx/include/atomic
```
template <class _Atp, class _Fn>
struct __libcpp_atomic_wait_backoff_impl {
_Atp* __a;
_Fn __test_fn;
_LIBCPP_AVAILABILITY_SYNC
_LIBCPP_INLINE_VISIBILITY bool operator()(chrono::nanoseconds __elapsed) const
{
if(__elapsed > chrono::microseconds(64))
{
auto const __monitor = __libcpp_atomic_monitor(__a);
if(__test_fn())
return true;
__libcpp_atomic_wait(__a, __monitor);
}
else if(__elapsed > chrono::microseconds(4))
__libcpp_thread_yield();
else
{} // poll
return false;
}
};
```
This could be your `wait` implmetation and it will work only in Clang.
I dubit it any way conform C++ in implmetation, but as whole confom
behavior of `wait` defined in standard text.


Another place where we have sitation like this is `std::vector` you
can't implmemt it in C++.
You can copy paste it implmetation and it will work but if you change
compiler it will break.


> --
> Std-Discussion mailing list
> Std-Discussion_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion

Received on 2022-07-18 21:11:19