|
Boost : |
From: Jody Hagins (jody-boost-011304_at_[hidden])
Date: 2005-06-10 14:59:37
I realized that the previous code snippet may be hard to follow, since
it was taken out of the middle of a member function. So, here if the
member function, in its entirety. Basically, consumer_wait_() is an
internal method of a message queue, and would be called from within any
get/pop function (i.e., any time a consumer asks for a piece of data off
the message queue). When consumer_wait_() returns, the lock is still
held, and there is at least one message in the queue. If, for some
reason, the consumer can not get the message, an exception is thrown.
In this code, an exception can be thrown:
1. the message queue has been shutdown
2. the message queue has been deactivated for GET operations
3. the timeout elapses while waiting for a message to arrive
4. timed_wait() or wait() throws:
1. an internal error in the condition variable/lock will generate a
lock_error() exception
2. a then thread_would_block() exception is generated if the mutex
type is null_mutex.
I guess all code could specialize on null_mutex, but I think what I have
added to boost::condition is reasonable for most uses (and the really
special ones can always specialize themselves).
template <typename Lock>
void consumer_wait_(
Lock & lock,
boost::xtime const * timeout)
{
struct auto_increment : private boost::noncopyable
{
auto_increment(unsigned int & t) : t_(t) { ++t_; }
~auto_increment() { --t_; }
private:
unsigned int & t_;
};
#ifndef NDEBUG
struct assertions : private boost::noncopyable
{
assertions(
Lock const & lock,
size_type const & msgcnt)
: lock_(lock)
, msgcnt_(msgcnt)
{
assert(this->lock_.locked());
}
~assertions()
{
assert(this->lock_.locked());
assert(this->msgcnt_ > 0);
}
Lock const & lock_;
size_type const & msgcnt_;
};
assertions assertions(lock, this->msgcnt_);
#endif // NDEBUG
while (this->is_empty_())
{
if (this->is_shutdown_())
{
throw shutdown_exception();
}
if (!this->is_get_active_());
{
throw get_inactive_exception();
}
auto_increment num_waiting(this->num_waiting_consumers_);
if (timeout)
{
if (!this->waiting_consumers_cv_.timed_wait(lock, *timeout))
{
throw timeout_exception();
}
}
else
{
this->waiting_consumers_cv_.wait(lock);
}
}
if (!this->is_get_active_())
{
throw get_inactive_exception();
}
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk