Date: Sun, 24 Jul 2022 21:33:23 -0400
On Sun, Jul 24, 2022 at 9:27 PM Nate Eldredge via Std-Discussion
<std-discussion_at_[hidden]> wrote:
>
> On Wed, 20 Jul 2022, Marcin Jaczewski via Std-Discussion wrote:
>
> > How could it be possible that after unblocking it loads old value?
> > load is atomic and value is already changed as it "happens before" a
> > call to `notify`.
>
> If you look back at the "perverse" implementation I posted before, where
> "blocking" is just a spin loop and "unblocking" is exiting that loop, the
> issue boils down to the fact that, when one relaxed store happens-before
> another, it does not follow that they will be observed by another thread
> in the same order. Perhaps this is the source of your confusion?
>
> So, if we do a typical store-store litmus test:
>
> thr1:
> a.store(true, std::memory_order_relaxed);
> b.store(true, std::memory_order_relaxed);
>
> thr2:
> b_tmp = b.load();
> a_tmp = a.load();
>
> it is entirely possible that we end up with b_tmp == true and a_tmp ==
> false.
The problem I have with this interpretation is that it invents a
side-channel of information that isn't actually there in the standard.
The `wait` and `notify_one` are both on `a`. They are also both atomic
operations. These cannot be considered anything less than "atomic
operations on `a`". They cannot be atomic operations on some other
atomic object because... there is no such object in the code. There is
only `a`.
So where does the freedom come from to make this "perverse
implementation" a reality?
<std-discussion_at_[hidden]> wrote:
>
> On Wed, 20 Jul 2022, Marcin Jaczewski via Std-Discussion wrote:
>
> > How could it be possible that after unblocking it loads old value?
> > load is atomic and value is already changed as it "happens before" a
> > call to `notify`.
>
> If you look back at the "perverse" implementation I posted before, where
> "blocking" is just a spin loop and "unblocking" is exiting that loop, the
> issue boils down to the fact that, when one relaxed store happens-before
> another, it does not follow that they will be observed by another thread
> in the same order. Perhaps this is the source of your confusion?
>
> So, if we do a typical store-store litmus test:
>
> thr1:
> a.store(true, std::memory_order_relaxed);
> b.store(true, std::memory_order_relaxed);
>
> thr2:
> b_tmp = b.load();
> a_tmp = a.load();
>
> it is entirely possible that we end up with b_tmp == true and a_tmp ==
> false.
The problem I have with this interpretation is that it invents a
side-channel of information that isn't actually there in the standard.
The `wait` and `notify_one` are both on `a`. They are also both atomic
operations. These cannot be considered anything less than "atomic
operations on `a`". They cannot be atomic operations on some other
atomic object because... there is no such object in the code. There is
only `a`.
So where does the freedom come from to make this "perverse
implementation" a reality?
Received on 2022-07-25 01:36:08