diff --git a/rak/priority_queue.h b/rak/priority_queue.h index f4e1ed9c..9edd3f21 100644 --- a/rak/priority_queue.h +++ b/rak/priority_queue.h @@ -74,6 +74,10 @@ public: base_type::pop_back(); } + void update() { + std::make_heap(begin(), end(), m_compare); + } + void push(const value_type& value) { base_type::push_back(value); std::push_heap(begin(), end(), m_compare); @@ -95,12 +99,8 @@ public: return true; } - // Removes 'itr' from the queue. This assumes 'itr' has been - // modified such that it has a higher priority than any other - // element in the queue. + // Removes 'itr' from the queue. void erase(iterator itr) { -// std::push_heap(begin(), ++itr, m_compare); -// pop(); base_type::erase(itr); std::make_heap(begin(), end(), m_compare); } diff --git a/rak/priority_queue_default.h b/rak/priority_queue_default.h index a7bba0ce..40fc09fe 100644 --- a/rak/priority_queue_default.h +++ b/rak/priority_queue_default.h @@ -127,14 +127,32 @@ priority_queue_erase(priority_queue_default* queue, priority_item* item) { if (!item->is_valid()) throw torrent::internal_error("priority_queue_erase(...) called on an invalid item."); - // Clear time before erasing to force it to the top. + // Unqueue it before erasing. item->clear_time(); - + if (!queue->erase(item)) throw torrent::internal_error("priority_queue_erase(...) could not find item in queue."); +} - if (queue->find(item) != queue->end()) - throw torrent::internal_error("priority_queue_erase(...) item still in queue."); +inline void +priority_queue_update(priority_queue_default* queue, priority_item* item, timer t) { + if (t == timer()) + throw torrent::internal_error("priority_queue_update(...) received a bad timer."); + + if (!item->is_valid()) + throw torrent::internal_error("priority_queue_update(...) called on an invalid item."); + + if (queue->find(item) == queue->end()) { + if (item->is_queued()) + throw torrent::internal_error("priority_queue_update(...) cannot insert an already queued item."); + + item->set_time(t); + queue->push(item); + + } else { + item->set_time(t); + queue->update(); + } } } diff --git a/src/core/curl_get.cc b/src/core/curl_get.cc index 30e461b0..25aef829 100644 --- a/src/core/curl_get.cc +++ b/src/core/curl_get.cc @@ -83,8 +83,7 @@ CurlGet::start() { // Normally libcurl should handle the timeout. But sometimes that doesn't // work right so we do a fallback timeout that just aborts the transfer. m_taskTimeout.slot() = std::bind(&CurlGet::receive_timeout, this); - priority_queue_erase(&taskScheduler, &m_taskTimeout); - priority_queue_insert(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5)); + priority_queue_update(&taskScheduler, &m_taskTimeout, cachedTime + rak::timer::from_seconds(m_timeout + 5)); } curl_easy_setopt(m_handle, CURLOPT_FORBID_REUSE, (long)1); diff --git a/src/core/curl_stack.cc b/src/core/curl_stack.cc index 05b628e0..5668d281 100644 --- a/src/core/curl_stack.cc +++ b/src/core/curl_stack.cc @@ -262,8 +262,7 @@ int CurlStack::set_timeout(void* handle, long timeout_ms, void* userp) { CurlStack* stack = (CurlStack*)userp; - priority_queue_erase(&taskScheduler, &stack->m_taskTimeout); - priority_queue_insert(&taskScheduler, &stack->m_taskTimeout, cachedTime + rak::timer::from_milliseconds(timeout_ms)); + priority_queue_update(&taskScheduler, &stack->m_taskTimeout, cachedTime + rak::timer::from_milliseconds(timeout_ms)); return 0; } diff --git a/src/core/view.cc b/src/core/view.cc index 272cd87c..3d66ff0a 100644 --- a/src/core/view.cc +++ b/src/core/view.cc @@ -145,8 +145,7 @@ struct view_downloads_filter : std::unary_function { void View::emit_changed() { - priority_queue_erase(&taskScheduler, &m_delayChanged); - priority_queue_insert(&taskScheduler, &m_delayChanged, cachedTime); + priority_queue_update(&taskScheduler, &m_delayChanged, cachedTime); } void diff --git a/src/display/manager.cc b/src/display/manager.cc index 84426703..6bdfd154 100644 --- a/src/display/manager.cc +++ b/src/display/manager.cc @@ -64,8 +64,7 @@ Manager::force_redraw() { void Manager::schedule(Window* w, rak::timer t) { - rak::priority_queue_erase(&m_scheduler, w->task_update()); - rak::priority_queue_insert(&m_scheduler, w->task_update(), t); + rak::priority_queue_update(&m_scheduler, w->task_update(), t); schedule_update(50000); } @@ -114,8 +113,7 @@ Manager::schedule_update(uint32_t minInterval) { } if (!m_taskUpdate.is_queued() || m_taskUpdate.time() > m_scheduler.top()->time()) { - rak::priority_queue_erase(&taskScheduler, &m_taskUpdate); - rak::priority_queue_insert(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval)); + rak::priority_queue_update(&taskScheduler, &m_taskUpdate, std::max(m_scheduler.top()->time(), m_timeLastUpdate + minInterval)); } }