From 6fa2efadbaf96f1a959b3ded0db90bdf4e7a02af Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Sun, 24 Oct 2010 02:06:46 +0000 Subject: [PATCH] Fix vector reallocation performance problem. Refs #4780. [SVN r66158] --- include/boost/asio/detail/timer_queue.hpp | 41 ++++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/include/boost/asio/detail/timer_queue.hpp b/include/boost/asio/detail/timer_queue.hpp index 2bcb4989..09eb8256 100644 --- a/include/boost/asio/detail/timer_queue.hpp +++ b/include/boost/asio/detail/timer_queue.hpp @@ -79,36 +79,37 @@ public: // function call may need to be interrupted and restarted. bool enqueue_timer(const time_type& time, per_timer_data& timer, timer_op* op) { - // Ensure that there is space for the timer in the heap. We reserve here so - // that the push_back below will not throw due to a reallocation failure. - heap_.reserve(heap_.size() + 1); - - timer.op_queue_.push(op); + // Enqueue the timer object. if (timer.prev_ == 0 && &timer != timers_) { + if (this->is_positive_infinity(time)) + { + // No heap entry is required for timers that never expire. + timer.heap_index_ = (std::numeric_limits::max)(); + } + else + { + // Put the new timer at the correct position in the heap. This is done + // first since push_back() can throw due to allocation failure. + timer.heap_index_ = heap_.size(); + heap_entry entry = { time, &timer }; + heap_.push_back(entry); + up_heap(heap_.size() - 1); + } + // Insert the new timer into the linked list of active timers. timer.next_ = timers_; timer.prev_ = 0; if (timers_) timers_->prev_ = &timer; timers_ = &timer; - - // Put the new timer at the correct position in the heap. - if (this->is_positive_infinity(time)) - { - timer.heap_index_ = (std::numeric_limits::max)(); - return false; // No need to interrupt reactor as timer never expires. - } - else - { - timer.heap_index_ = heap_.size(); - heap_entry entry = { time, &timer }; - heap_.push_back(entry); - up_heap(heap_.size() - 1); - } } - return (heap_[0].timer_ == &timer); + // Enqueue the individual timer operation. + timer.op_queue_.push(op); + + // Interrupt reactor only if newly added timer is first to expire. + return timer.heap_index_ == 0 && timer.op_queue_.front() == op; } // Whether there are no timers in the queue.