|
Boost : |
From: williamkempf_at_[hidden]
Date: 2001-10-11 16:42:40
--- In boost_at_y..., "George A. Heintzelman" <georgeh_at_a...> wrote:
>
> Hi boosters,
>
> Summary question: Why does boost::condition::timed_wait require a
> ScopedTimedLock in its implementation? It doesn't appear that the
> ScopedTimedLock properties are necessary to the timed wait itself...
>
> Background:
> I'm trying to do a simplistic thread-cancellation model without
thread
> cancellation in boost::Threads. I have a thread which I want to
wake up
> periodically, process requests which have accumulated, and then go
back
> to sleep. (There are reasons for not wanting continuous processing,
but
> I won't go into that).
>
> However, if the parent thread is dying, I want this child thread to
be
> signalled, wake up before its time, process any last requests, and
then
> exit. So I implemented this with a loop:
>
> bool done = false;
> while(!done) {
> boost::xtime xt;
> xtime_get(&xt,boost::TIME_UTC);
> xt.sec += transmission_delay;
> boost::timed_mutex::scoped_timed_lock
> termination_lock(pimpl->termination_mutex, true);
> pimpl->termination_condition.timed_wait(termination_lock, xt);
> done = terminate;
>
> // Do other processing...
>
> }
>
> Where terminate will be set by another procedure locking then
releasing
> the termination mutex.
>
> My question is: why do I need to use a timed_mutex and
> scoped_timed_lock in this case? I'm not going to have the lock
expire,
> just the wait. And this makes me put this 'true' parameter in there
> which is rather non-transparent, shall we say...
>
> Not that it's really HARD to do, I'm just curious as to whether
there's
> something more subtle being done inside timed_wait, or whether
> restrictions could be loosened.
A "condition variable", which is what the boost::condition type is,
must work in conjunction with shared data and a mutex. The mutex
must be locked before calls to wait, while the wait operation
atomically unlocks the mutex, waits for the signal and re-locks the
mutex. This insures that the mutex is locked before the wait and
after the wait with no race conditions. The reason that a mutex must
be involved at all is because the condition is waiting for some state
identified by shared data and in order to test the shared data the
whole process must occur within code protected by a locked mutex.
Boost.Threads uses a scoped_lock parameter instead of the more
traditional mutex parameter to insure the mutex is locked.
Looking at your code it appears that you've misused the condition
type (though I may be wrong since I can't see all of your code).
Taking your description the whole process should be something more
like this (poor implementation, but written this way for clarity of
the concept):
// in parent thread when it terminates...
{
boost::mutex::scoped_lock lock(child->mutex);
child->teminate = true;
}
// in child thread...
{
boost::mutex::scoped_lock lock
boost::xtime xt;
xtime_get(&xt, boost::TIME_UTC);
xt.sec += transmission_delay;
while (!terminate) {
if (!cond.timed_wait(lock, xt))
break;
}
if (terminate)
// handle termination here
}
// other processing here
Bill Kempf
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk