From 6e976616a0058288011bd92d887fead345b3ef59 Mon Sep 17 00:00:00 2001 From: kannibalox Date: Thu, 17 Oct 2024 16:16:17 -0400 Subject: [PATCH] Simplify updating queue entries The erase/insert pattern can be replaced by a single method that updates an existing entry's timer, or inserting if it doesn't exist. This has much less impact than the libtorrent change it's based on, but might as well be consistent. --- rak/priority_queue.h | 10 +++++----- rak/priority_queue_default.h | 26 ++++++++++++++++++++++---- src/core/curl_get.cc | 3 +-- src/core/curl_stack.cc | 3 +-- src/core/view.cc | 3 +-- src/display/manager.cc | 6 ++---- 6 files changed, 32 insertions(+), 19 deletions(-) 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)); } }