Boost logo

Boost :

Subject: Re: [boost] [thread] Request review of new synchronisation object, boost::permit<>
From: Peter Dimov (lists_at_[hidden])
Date: 2014-05-05 10:26:52

"You will never see spurious wakeups from a permit object -- [...]. This
means you don't need to do any wait predicate checking with permits..."

I don't think that this is true. Suppose we have two producer threads Tp1
and Tp2 and two consumer treads Tc1 and Tc2, and a predicate P. I'll treat
the predicate as a simple boolean variable below, for simplicity.

A producer thread sets P=1 and calls notify_one. A consumer thread calls
wait and then sets P=0. (It has to set P=0 regardless of how many producers
have set the predicate to 1, because - I assume - the permit object doesn't
count the pending notify_one calls, unlike a semaphore and like an event.)

So you have

Initially P is 0.
Tc1, Tc2 call wait.
Tp1 sets P=1 and calls notify_one. Tc1 is unblocked, returns from wait, but
is immediately suspended by the scheduler for unfathomable scheduling
reasons, like its code causing a page fault.
Tp2 sets P=1 and calls notify_one. Tc2 is unblocked, returns from wait, sets
Tc1 is resumed, sees P=0, panics.

I suspect that your guarantees, that grant/notify_one calls are blocking and
mutually exclusive, were designed to prevent this, but they don't and can't,
in theory. They _can_ make the above extremely improbable, but they aren't
theoretically sound.

The specification of condition variables allows spurious wakeups not because
they can't be prevented by the implementation; it permits spurious wakeups
to make client code assume spurious wakeups, because code that is written to
assume spurious wakeups is more likely to be correct. Or conversely, code
that does not assume spurious wakeups is likely to be incorrect even if no
spurious wakeups occur.

Boost list run by bdawes at, gregod at, cpdaniel at, john at