Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-10-16 18:02:30


Jonathan Biggar <jon_at_[hidden]> writes:

> David Abrahams wrote:
> > * On condition.html
> >
> > a. What is the effective difference between notify_one() and
> > notify_all()? In the absence of any information about the
> > underlying system's scheduling mechanism, it seems as though there
> > is none: either way, one blocked thread will get to execute with
> > the mutex locked. If there is a difference between the two in
> > practice, the documentation should give some indication of it.
>
> This would depend on whether the condition variable has a deterministic
> thread queueing model like FIFO, or picks threads at random to wakeup.
> That in turn, depends on the particular implementation behavior that the
> OS provides.

Yes, I realize that. I was speaking from the perspective of a user who
comes to Boost.Threads without any knowledge of the underlying
implementation. My point is that the documentation should refer the
user to the platform docs and describe the possible consequences of
the different queueing models.

> > b. What is the rationale for condition::wait() throwing lock_error
> > if !lock.locked()? Would it not be cleaner to simply lock the lock
> > if it arrives in an unlocked condition?
>
> It is almost certainly an error to call condition::wait() without having
> the lock, since the application code is responsible for testing the
> application data that the condition and lock protect. If you aren't
> holding the lock, you either have a race condition or a deadlock
> lurking.

I also realize that, given the way condition::wait() is
implemented. Did you read my 2nd sentence? If I don't have the lock,
and I want to wait on the condition, why shouldn't it just acquire the
lock for me? Use case: the condition protects some input queue. I want
to block until some data is available in the queue. I don't need to
touch the queue until there's data ready, so I have no reason to lock
the mutex ahead of time other than that's what the condition interface
asks me to do.

It's always more pleasant to use an interface which "always works"
than one which throws at you to let you know it doesn't like the state
of your inputs.

> > d. If the predicate form of wait(lock, pred) were implemented the
> > way it's specified, there would be a race condition:
> >
> > while (!pred()) wait(lock);
> >
> > Since the predicate is checked before the non-predicate form checks
> > for the lock being locked and throws an exception. Fortunately,
> > your implementation doesn't work that way.
>
> This is only a race condition if the code violates the pre-condition
> that the lock must be locked before testing the predicate and calling
> wait().

It's not a precondition. The behavior in case the lock is not lock is
well-defined by the documentation, and lock.locked() is not in the
Requires: clause. It doesn't make sense to specify behavior in the
case of precondition violations.

> > However, I think I like:
> >
> > do { wait(lock) } while(!pred());
> >
> > better.
>
> This deadlocks if the predicate is already true before the loop is
> entered!

I think you're right. Oops.

> > e. misuse of the term `model'. Types model Concepts, objects do
> > not. You should just be saying "mutex object", not "mutex model".
> >
> > f. The non-predicate form of timed_wait Effects: clause ends with
> > "...and then reacquires the lock". This appears to mean the lock is
> > reacquired regardless of whether timeout arrives before
> > notification. I think that can't be intentional. Can it?
>
> Yes, that is intentional. The required condition variable pre- and
> post-condition logic for wait() is that the associated lock is locked.
> Without that, you get race conditions.

Only if you access the associated data, right? Well, it wasn't
completely clear to me that that was supposed to be allowed in the
case of timeout. It means that even with a timeout, you can't come
back from wait() if some other thread has the mutex locked. I think it
would be good to spell that out somewhere in the condition docs.

-- 
                    David Abrahams
dave_at_[hidden] * http://www.boost-consulting.com
Building C/C++ Extensions for Python: Dec 9-11, Austin, TX
http://www.enthought.com/training/building_extensions.html

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk