2
0
mirror of https://github.com/boostorg/asio.git synced 2026-01-28 06:42:08 +00:00

Don't cleanup pending timer objects while the reactor lock is held, since

the destructors for the objects may try to make calls back into the
reactor.


[SVN r38319]
This commit is contained in:
Christopher Kohlhoff
2007-07-31 11:33:29 +00:00
parent 3f41710b85
commit 788d350ec5
2 changed files with 52 additions and 6 deletions

View File

@@ -49,7 +49,9 @@ public:
// Constructor.
timer_queue()
: timers_(),
heap_()
heap_(),
cancelled_timers_(0),
cleanup_timers_(0)
{
}
@@ -112,12 +114,17 @@ public:
{
timer_base* t = heap_[0];
remove_timer(t);
t->prev_ = 0;
t->next_ = cleanup_timers_;
cleanup_timers_ = t;
t->invoke(boost::system::error_code());
}
}
// Cancel the timer with the given token. The handler will be invoked
// immediately with the result operation_aborted.
// Cancel the timers with the given token. Any timers pending for the token
// will be notified that they have been cancelled next time
// dispatch_cancellations is called. Returns the number of timers that were
// cancelled.
std::size_t cancel_timer(void* timer_token)
{
std::size_t num_cancelled = 0;
@@ -130,7 +137,9 @@ public:
{
timer_base* next = t->next_;
remove_timer(t);
t->invoke(boost::asio::error::operation_aborted);
t->prev_ = 0;
t->next_ = cancelled_timers_;
cancelled_timers_ = t;
t = next;
++num_cancelled;
}
@@ -138,6 +147,31 @@ public:
return num_cancelled;
}
// Dispatch any pending cancels for timers.
virtual void dispatch_cancellations()
{
while (cancelled_timers_)
{
timer_base* this_timer = cancelled_timers_;
cancelled_timers_ = this_timer->next_;
this_timer->next_ = cleanup_timers_;
cleanup_timers_ = this_timer;
this_timer->invoke(boost::asio::error::operation_aborted);
}
}
// Destroy timers that are waiting to be cleaned up.
virtual void cleanup_timers()
{
while (cleanup_timers_)
{
timer_base* next_timer = cleanup_timers_->next_;
cleanup_timers_->next_ = 0;
cleanup_timers_->destroy();
cleanup_timers_ = next_timer;
}
}
// Destroy all timers.
virtual void destroy_timers()
{
@@ -152,6 +186,7 @@ public:
}
heap_.clear();
timers_.clear();
cleanup_timers();
}
private:
@@ -239,8 +274,7 @@ private:
static void invoke_handler(timer_base* base,
const boost::system::error_code& result)
{
std::auto_ptr<timer<Handler> > t(static_cast<timer<Handler>*>(base));
t->handler_(result);
static_cast<timer<Handler>*>(base)->handler_(result);
}
// Destroy the handler.
@@ -339,6 +373,12 @@ private:
// The heap of timers, with the earliest timer at the front.
std::vector<timer_base*> heap_;
// The list of timers to be cancelled.
timer_base* cancelled_timers_;
// The list of timers to be destroyed.
timer_base* cleanup_timers_;
};
} // namespace detail

View File

@@ -45,6 +45,12 @@ public:
// Dispatch all ready timers.
virtual void dispatch_timers() = 0;
// Dispatch any pending cancels for timers.
virtual void dispatch_cancellations() = 0;
// Destroy timers that are waiting to be cleaned up.
virtual void cleanup_timers() = 0;
// Destroy all timers.
virtual void destroy_timers() = 0;
};