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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user