Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2006-10-08 10:53:28

Roland Schwarz wrote:

>> He can, but this kind of defeats the purpose of using the predicate
>> version in the first place. It is supposed to guard against spurious
>> wakeups, so it makes sense to also make it guard against stolen
>> wakeups.
> I agree we could change semantics this way, but I still cannot
> understand why you think the wakeup is stolen? You have access
> to it by evaluating pred.

"Spurious wakeup" means that a thread is awakened without reason. "Stolen
wakeup" means that a thread consumes a wakeup intended for another thread.
When a timeout expires _and_ the thread consumes a signal, this signal in a
perfect world (where only one of the two events occur at a given moment)
would have been delivered to another waiting thread. Hence, "stolen wakeup".

You have two threads waiting on a condition, two events happen at the same
time, a signal and the first thread timing out. Delivering both to the first
thread is error prone. Most client code that uses timed waits does not
handle this situation.

> Say we have a thread that makes a call to start an external
> device e.g. a motor at time t0. Say we have a second thread
> that is monitoring the RPM of the motor and signalling a
> condition if it has reached its nominal value. The first
> thread meanwhile is waiting on this condition with a timed
> wait say t0+t_emergency. Now lets assume motor specs. dictate
> it is essential to immediately stop the device if it hasn't
> reached nominal RPM within t_emergency. Doesn't your
> proposed change just hide this fact, and the motor thus
> might break?

Why would it hide it?

> But again, I think I possibly cannot see your point clear
> enough yet. Can we agree that the current version is not
> wrong?

It does what the specification says it does, so it is not "wrong" in this
sense. I'm arguing that the specification needs to be changed.

> You are just suggesting a possibly better less
> error prone semantics? If so please try to elaborate it
> a little more.

The idea of supplying a predicate version is to guard against common user
mistakes. For the ordinary wait, the predicate version ignores spurious
wakeups. It is very easy to assume that spurious wakeups don't occur and
write incorrect code based on this assumption. So we supply a version where
they don't.

For timed_wait, there is an additional source of subtle bugs, the fact that
a timeout and a signal can both occur and be "delivered" to the same waiting
thread. You can't express this in a simple true/false return value, so you
have to map the three possible outcomes into two (the fourth outcome is a
spurious wakeup and is never returned). I argue that the predicate version
should attempt to guard against this additional incorrect user assumption
(that only one of a signal occuring or a timeout elapsing happens and not
both), too.

To get back to you example,

if (!timed_wait(lk, xt, pred) && !pred()) {
   // handle timeout

have you ever seen such code? I haven't.

if (!timed_wait(lk, xt, pred) ) {
   // handle timeout

is the norm (and pred is usually something lambda-ish).

The low-level non-predicate version is available for those that are
interested in the "raw" return value from the wait.

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