Boost logo

Boost :

From: Jonathan Biggar (jon_at_[hidden])
Date: 2002-10-16 21:53:40


David Abrahams wrote:
> > I've never seen a workable use case for calling wait() on a
> > condition without performing some test on the data that the
> > condition is protectiong, and that means the lock has to be acquired
> > first. That's the basic design pattern for using locks & condition
> > variables:
> >
> > lock->acquire();
> > while (!predicate())
> > cond.wait();
> > // modify protected data here
> > lock->release();
>
> Right. But I'm suggesting that everything up to the comment can be
> encapsultated in the version of wait that takes the predicate.

It's not very symmetrical to have the lock acquisition inside the wait()
call, but the release() outside, though, and makes using a lock guard
problematical.

Although you could have a version of wait that takes another template
"action" functor, and call it like this:

        cond.wait(predicate, action);

and encapsulate the loop entirely.

> > Of course to be exception safe, you use a lock guard rather than
> > just acquiring and releasing the lock.
>
> 'course.
>
> > > 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.
> >
> > It would be nice, but that's not the way to make this "always work".
>
> Maybe I'm still missing something, but I don't see it yet. The version
> of wait that takes a predicate already contains code for testing the
> predicate and in a loop. I don't see a reason to make the user test it
> and branch around the wait. But then, maybe I'm describing a slightly
> higher-level construct that just shouldn't be called a condition wait.

Perhaps like I suggested above?

> > > > > 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.
> >
> > Right, but you have to access the associated data to see if you are
> > going to call cond.timed_wait() in the first place.
>
> No, I mean /after/ the return from timed_wait. At that point, if you
> aren't going to touch the data, you don't need to have the mutex. If
> you're going to touch it regardless of whether notify() occurred. You
> need it.

I've seen use cases where you have to do some "clean up" after the
timeout that still needs to have the lock held. If timed_wait()
released the lock, you wouldn't be able to do that.

-- 
Jon Biggar
Floorboard Software
jon_at_[hidden]
jon_at_[hidden]

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