From 12ef47da3cbcce5093f8a65725d6fb20092a4110 Mon Sep 17 00:00:00 2001 From: rakshasa Date: Thu, 8 Dec 2005 21:19:53 +0000 Subject: [PATCH] * Replaced TaskScheduler with rak::priority_queue. * Fixed an exception caused by initial hash check not properly cleaning up HashQueue when canceling. git-svn-id: svn://rakshasa.no/libtorrent/trunk/rtorrent@606 e378c898-3ddf-0310-93e7-cc216c733640 --- Makefile.am | 2 + rak/functional.h | 78 +++++++------ rak/functional_fun.h | 76 ++++++------- rak/priority_queue.h | 101 +++++++++++++++++ rak/priority_queue_default.h | 134 +++++++++++++++++++++++ src/control.cc | 5 +- src/control.h | 2 +- src/core/download_factory.cc | 7 +- src/core/download_factory.h | 6 +- src/display/manager.cc | 7 +- src/display/window.cc | 1 - src/display/window.h | 6 +- src/display/window_download_list.cc | 2 +- src/display/window_download_statusbar.cc | 2 +- src/display/window_file_list.cc | 2 +- src/display/window_http_queue.cc | 2 +- src/display/window_peer_info.cc | 2 +- src/display/window_peer_list.cc | 2 +- src/display/window_statusbar.cc | 2 +- src/display/window_title.cc | 2 +- src/display/window_tracker_list.cc | 2 +- src/globals.cc | 6 +- src/globals.h | 9 +- src/main.cc | 14 ++- src/ui/download_list.cc | 5 +- src/ui/download_list.h | 2 +- src/utils/Makefile.am | 5 +- src/utils/task_item.h | 74 ------------- src/utils/task_scheduler.cc | 93 ---------------- src/utils/task_scheduler.h | 78 ------------- 30 files changed, 362 insertions(+), 367 deletions(-) create mode 100644 rak/priority_queue.h create mode 100644 rak/priority_queue_default.h delete mode 100644 src/utils/task_item.h delete mode 100644 src/utils/task_scheduler.cc delete mode 100644 src/utils/task_scheduler.h diff --git a/Makefile.am b/Makefile.am index 240e0972..3a1be6ad 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,8 @@ EXTRA_DIST= \ rak/error_number.h \ rak/functional.h \ rak/functional_fun.h \ + rak/priority_queue.h \ + rak/priority_queue_default.h \ rak/string_manip.h \ rak/timer.h \ rak/unordered_vector.h \ diff --git a/rak/functional.h b/rak/functional.h index dc5a6721..c96501e1 100644 --- a/rak/functional.h +++ b/rak/functional.h @@ -211,6 +211,12 @@ greater_equal(Type t, Ftor f) { return greater_equal_t(t, f); } +template +struct invert : public std::unary_function { + Tp + operator () (const Tp& x) const { return ~x; } +}; + template struct on_t : public std::unary_function { typedef typename Dest::result_type result_type; @@ -343,12 +349,12 @@ bind2nd(const Operation& op, const Type& val) { // of using a seperate functor for that. template -class mem_fn0 { +class mem_fun0 { public: typedef Ret (Object::*Function)(); - mem_fn0() : m_object(NULL) {} - mem_fn0(Object* o, Function f) : m_object(o), m_function(f) {} + mem_fun0() : m_object(NULL) {} + mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {} bool is_valid() const { return m_object; } @@ -360,12 +366,12 @@ private: }; template -class const_mem_fn0 { +class const_mem_fun0 { public: typedef Ret (Object::*Function)() const; - const_mem_fn0() : m_object(NULL) {} - const_mem_fn0(Object* o, Function f) : m_object(o), m_function(f) {} + const_mem_fun0() : m_object(NULL) {} + const_mem_fun0(Object* o, Function f) : m_object(o), m_function(f) {} bool is_valid() const { return m_object; } @@ -377,12 +383,12 @@ private: }; template -class mem_fn1 { +class mem_fun1 { public: typedef Ret (Object::*Function)(Arg1); - mem_fn1() : m_object(NULL) {} - mem_fn1(Object* o, Function f) : m_object(o), m_function(f) {} + mem_fun1() : m_object(NULL) {} + mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {} bool is_valid() const { return m_object; } @@ -394,12 +400,12 @@ private: }; template -class const_mem_fn1 { +class const_mem_fun1 { public: typedef Ret (Object::*Function)(Arg1) const; - const_mem_fn1() : m_object(NULL) {} - const_mem_fn1(Object* o, Function f) : m_object(o), m_function(f) {} + const_mem_fun1() : m_object(NULL) {} + const_mem_fun1(Object* o, Function f) : m_object(o), m_function(f) {} bool is_valid() const { return m_object; } @@ -411,12 +417,12 @@ private: }; template -class mem_fn2 : public std::binary_function { +class mem_fun2 : public std::binary_function { public: typedef Ret (Object::*Function)(Arg1, Arg2); - mem_fn2() : m_object(NULL) {} - mem_fn2(Object* o, Function f) : m_object(o), m_function(f) {} + mem_fun2() : m_object(NULL) {} + mem_fun2(Object* o, Function f) : m_object(o), m_function(f) {} bool is_valid() const { return m_object; } @@ -428,12 +434,12 @@ private: }; template -class mem_fn3 { +class mem_fun3 { public: typedef Ret (Object::*Function)(Arg1, Arg2, Arg3); - mem_fn3() : m_object(NULL) {} - mem_fn3(Object* o, Function f) : m_object(o), m_function(f) {} + mem_fun3() : m_object(NULL) {} + mem_fun3(Object* o, Function f) : m_object(o), m_function(f) {} bool is_valid() const { return m_object; } @@ -445,39 +451,39 @@ private: }; template -inline mem_fn0 -make_mem_fn(Object* o, Ret (Object::*f)()) { - return mem_fn0(o, f); +inline mem_fun0 +make_mem_fun(Object* o, Ret (Object::*f)()) { + return mem_fun0(o, f); } template -inline const_mem_fn0 -make_mem_fn(Object* o, Ret (Object::*f)() const) { - return const_mem_fn0(o, f); +inline const_mem_fun0 +make_mem_fun(Object* o, Ret (Object::*f)() const) { + return const_mem_fun0(o, f); } template -inline mem_fn1 -make_mem_fn(Object* o, Ret (Object::*f)(Arg1)) { - return mem_fn1(o, f); +inline mem_fun1 +make_mem_fun(Object* o, Ret (Object::*f)(Arg1)) { + return mem_fun1(o, f); } template -inline const_mem_fn1 -make_mem_fn(Object* o, Ret (Object::*f)(Arg1) const) { - return const_mem_fn1(o, f); +inline const_mem_fun1 +make_mem_fun(Object* o, Ret (Object::*f)(Arg1) const) { + return const_mem_fun1(o, f); } template -inline mem_fn2 -make_mem_fn(Object* o, Ret (Object::*f)(Arg1, Arg2)) { - return mem_fn2(o, f); +inline mem_fun2 +make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2)) { + return mem_fun2(o, f); } template -inline mem_fn3 -make_mem_fn(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) { - return mem_fn3(o, f); +inline mem_fun3 +make_mem_fun(Object* o, Ret (Object::*f)(Arg1, Arg2, Arg3)) { + return mem_fun3(o, f); } } diff --git a/rak/functional_fun.h b/rak/functional_fun.h index 7d4dc850..e9eaff2d 100644 --- a/rak/functional_fun.h +++ b/rak/functional_fun.h @@ -53,36 +53,36 @@ namespace rak { -template +template class function_base { public: virtual ~function_base() {} - virtual _Result operator () () = 0; + virtual Result operator () () = 0; }; -template +template struct function_ref { - explicit function_ref(_Base* b) : m_base(b) {} + explicit function_ref(Base* b) : m_base(b) {} - _Base* m_base; + Base* m_base; }; -template +template class function { public: - typedef _Result result_type; - typedef function_base<_Result> _Base; + typedef Result result_type; + typedef function_base Base; function() : m_base(0) {} - function(function_ref<_Base> f) : m_base(f.m_base) {} - explicit function(function_base<_Result>* base) { m_base = base; } + function(function_ref f) : m_base(f.m_base) {} + explicit function(function_base* base) { m_base = base; } ~function() { delete m_base; } function& operator = (function& f) { m_base = f.release(); return *this; } - function& operator = (function_ref<_Base> f) { + function& operator = (function_ref f) { if (m_base != f.m_base) { delete m_base; m_base = f.m_base; @@ -91,57 +91,57 @@ public: return *this; } - template - operator function_ref<_T> () { return function_ref<_T>(this->release()); } + template + operator function_ref () { return function_ref(this->release()); } - _Result operator () () { return (*m_base)(); } + Result operator () () { return (*m_base)(); } private: - _Base* release() { _Base* tmp = m_base; m_base = 0; return tmp; } + Base* release() { Base* tmp = m_base; m_base = 0; return tmp; } - _Base* m_base; + Base* m_base; }; -template -class _mem_fn0 : public function_base<_Result> { +template +class _mem_fn0 : public function_base { public: - typedef _Result (_Object::*_Func)(); + typedef Result (Object::*Func)(); - _mem_fn0(_Object* object, _Func func) : m_object(object), m_func(func) {} + _mem_fn0(Object* object, Func func) : m_object(object), m_func(func) {} virtual ~_mem_fn0() {} - virtual _Result operator () () { return (m_object->*m_func)(); } + virtual Result operator () () { return (m_object->*m_func)(); } private: - _Object* m_object; - _Func m_func; + Object* m_object; + Func m_func; }; -template -class _const_mem_fn0 : public function_base<_Result> { +template +class _const_mem_fn0 : public function_base { public: - typedef _Result (_Object::*_Func)() const; + typedef Result (Object::*Func)() const; - _const_mem_fn0(const _Object* object, _Func func) : m_object(object), m_func(func) {} + _const_mem_fn0(const Object* object, Func func) : m_object(object), m_func(func) {} virtual ~_const_mem_fn0() {} - virtual _Result operator () () { return (m_object->*m_func)(); } + virtual Result operator () () { return (m_object->*m_func)(); } private: - const _Object* m_object; - _Func m_func; + const Object* m_object; + Func m_func; }; -template -function<_Result> -mem_fn(_Object* object, _Result (_Object::*func)()) { - return function<_Result>(static_cast*>(new _mem_fn0<_Object, _Result>(object, func))); +template +function +mem_fn(Object* object, Result (Object::*func)()) { + return function(static_cast*>(new _mem_fn0(object, func))); } -template -function<_Result> -mem_fn(const _Object* object, _Result (_Object::*func)() const) { - return function<_Result>(static_cast*>(new _const_mem_fn0<_Object, _Result>(object, func))); +template +function +mem_fn(const Object* object, Result (Object::*func)() const) { + return function(static_cast*>(new _const_mem_fn0(object, func))); } } diff --git a/rak/priority_queue.h b/rak/priority_queue.h new file mode 100644 index 00000000..8185b09b --- /dev/null +++ b/rak/priority_queue.h @@ -0,0 +1,101 @@ +// rak - Rakshasa's toolbox +// Copyright (C) 2005, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +// priority_queue is a priority queue implemented using a binary +// heap. It can contain multiple instances of a value. + +#ifndef RAK_PRIORITY_QUEUE_H +#define RAK_PRIORITY_QUEUE_H + +#include +#include +#include + +namespace rak { + +template +class priority_queue : public std::vector { +public: + typedef std::vector base_type; + typedef typename base_type::reference reference; + typedef typename base_type::const_reference const_reference; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::value_type value_type; + + using base_type::size; + using base_type::empty; + + priority_queue(Compare l = Compare(), Equal e = Equal(), Remove r = Remove()) + : m_compare(l), m_equal(e), m_remove(r) {} + + const_reference top() const { + return base_type::front(); + } + + void pop() { + std::pop_heap(base_type::begin(), base_type::end(), m_compare); + base_type::pop_back(); + } + + void push(const value_type& value) { + base_type::push_back(value); + std::push_heap(base_type::begin(), base_type::end(), m_compare); + } + + // Removes 'value' from the queue. The Remove functor must change the + // priority of the value such that it comes before any other in the + // queue. + void erase(value_type value) { + iterator itr = std::find_if(base_type::begin(), base_type::end(), std::bind2nd(m_equal, value)); + + if (itr == base_type::end()) + return; + + m_remove(*itr); + std::push_heap(base_type::begin(), ++itr, m_compare); + pop(); + } + +private: + Compare m_compare; + Equal m_equal; + Remove m_remove; +}; + +} + +#endif diff --git a/rak/priority_queue_default.h b/rak/priority_queue_default.h new file mode 100644 index 00000000..da8b3f87 --- /dev/null +++ b/rak/priority_queue_default.h @@ -0,0 +1,134 @@ +// rak - Rakshasa's toolbox +// Copyright (C) 2005, Jari Sundell +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// In addition, as a special exception, the copyright holders give +// permission to link the code of portions of this program with the +// OpenSSL library under certain conditions as described in each +// individual source file, and distribute linked combinations +// including the two. +// +// You must obey the GNU General Public License in all respects for +// all of the code used other than OpenSSL. If you modify file(s) +// with this exception, you may extend this exception to your version +// of the file(s), but you are not obligated to do so. If you do not +// wish to do so, delete this exception statement from your version. +// If you delete this exception statement from all source files in the +// program, then also delete it here. +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RAK_PRIORITY_QUEUE_DEFAULT_H +#define RAK_PRIORITY_QUEUE_DEFAULT_H + +#include +#include +#include +#include +#include + +namespace rak { + +class priority_item { +public: + bool is_queued() const { return m_time != timer(); } + + void call() { m_slot(); } + void set_slot(function s) { m_slot = s; } + + const timer& time() const { return m_time; } + void clear_time() { m_time = timer(); } + + priority_item* prepare(const timer& t); + +private: + timer m_time; + function m_slot; +}; + +inline priority_item* +priority_item::prepare(const timer& t) { + if (is_queued()) + throw std::logic_error("priority_item::prepare(rak::timer) called on an already queued item."); + + m_time = t; + return this; +} + +struct priority_compare { + bool operator () (const priority_item* p1, const priority_item* p2) const { + return p1->time() > p2->time(); + } +}; + +struct priority_erase { + void operator () (priority_item* p1) const { + p1->clear_time(); + } +}; + +typedef std::equal_to priority_equal; +typedef priority_queue priority_queue_default; + +template +class queue_pop_iterator + : public std::iterator { +public: + typedef Queue container_type; + + queue_pop_iterator() : m_queue(NULL) {} + queue_pop_iterator(Queue* q, Compare c) : m_queue(q), m_compare(c) {} + + queue_pop_iterator& operator ++ () { m_queue->pop(); return *this; } + queue_pop_iterator& operator ++ (int) { m_queue->pop(); return *this; } + + typename container_type::const_reference operator * () { return m_queue->top(); } + + bool operator != (const queue_pop_iterator& itr) { return !m_queue->empty() && m_compare(m_queue->top()); } + bool operator == (const queue_pop_iterator& itr) { return m_queue->empty() || !m_compare(m_queue->top()); } + +private: + Queue* m_queue; + Compare m_compare; +}; + +struct priority_ready { + priority_ready() {} + priority_ready(timer t) : m_timer(t) {} + + bool operator () (const priority_item* p1) const { + return p1->time() <= m_timer; + } + + timer m_timer; +}; + +inline queue_pop_iterator +queue_popper(priority_queue_default& queue, priority_ready comp) { + return queue_pop_iterator(&queue, comp); +} + +inline queue_pop_iterator +queue_popper() { + return queue_pop_iterator(); +} + +} + +#endif diff --git a/src/control.cc b/src/control.cc index e1d28875..4c21ea1e 100644 --- a/src/control.cc +++ b/src/control.cc @@ -59,7 +59,6 @@ Control::Control() : m_inputStdin->slot_pressed(sigc::mem_fun(m_input, &input::Manager::pressed)); - m_taskShutdown.set_iterator(taskScheduler.end()); m_taskShutdown.set_slot(rak::mem_fn(this, &Control::receive_shutdown)); } @@ -113,8 +112,8 @@ Control::receive_shutdown() { m_core->shutdown(false); m_shutdownReceived = true; - if (!taskScheduler.is_scheduled(&m_taskShutdown)) - taskScheduler.insert(&m_taskShutdown, cachedTime + 5 * 1000000); + if (!m_taskShutdown.is_queued()) + taskScheduler.push(m_taskShutdown.prepare(cachedTime + 5 * 1000000)); } else { m_core->shutdown(true); diff --git a/src/control.h b/src/control.h index d12803a6..b5b5fe89 100644 --- a/src/control.h +++ b/src/control.h @@ -89,7 +89,7 @@ private: input::Manager* m_input; input::InputEvent* m_inputStdin; - utils::TaskItem m_taskShutdown; + rak::priority_item m_taskShutdown; }; #endif diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc index 359ece6b..72c9a0ba 100644 --- a/src/core/download_factory.cc +++ b/src/core/download_factory.cc @@ -60,10 +60,7 @@ DownloadFactory::DownloadFactory(const std::string& uri, Manager* m) : m_session(false), m_start(false) { - m_taskLoad.set_iterator(taskScheduler.end()); m_taskLoad.set_slot(rak::mem_fn(this, &DownloadFactory::receive_load)); - - m_taskCommit.set_iterator(taskScheduler.end()); m_taskCommit.set_slot(rak::mem_fn(this, &DownloadFactory::receive_commit)); } @@ -77,12 +74,12 @@ DownloadFactory::~DownloadFactory() { void DownloadFactory::load() { - taskScheduler.insert(&m_taskLoad, cachedTime); + taskScheduler.push(m_taskLoad.prepare(cachedTime)); } void DownloadFactory::commit() { - taskScheduler.insert(&m_taskCommit, cachedTime); + taskScheduler.push(m_taskCommit.prepare(cachedTime)); } void diff --git a/src/core/download_factory.h b/src/core/download_factory.h index d255d30c..70a37a47 100644 --- a/src/core/download_factory.h +++ b/src/core/download_factory.h @@ -39,8 +39,8 @@ #include #include +#include -#include "utils/task_item.h" #include "http_queue.h" namespace core { @@ -87,8 +87,8 @@ private: bool m_start; Slot m_slotFinished; - utils::TaskItem m_taskLoad; - utils::TaskItem m_taskCommit; + rak::priority_item m_taskLoad; + rak::priority_item m_taskCommit; }; } diff --git a/src/display/manager.cc b/src/display/manager.cc index c4e8f6e8..e13e6659 100644 --- a/src/display/manager.cc +++ b/src/display/manager.cc @@ -98,7 +98,12 @@ void Manager::do_update() { Canvas::refresh_std(); - displayScheduler.execute(cachedTime); + std::list workQueue; + + std::copy(rak::queue_popper(displayScheduler, rak::priority_ready(cachedTime)), rak::queue_popper(), std::back_inserter(workQueue)); + std::for_each(workQueue.begin(), workQueue.end(), std::mem_fun(&rak::priority_item::clear_time)); + std::for_each(workQueue.begin(), workQueue.end(), std::mem_fun(&rak::priority_item::call)); + std::for_each(begin(), end(), rak::if_then(std::mem_fun(&Window::is_active), std::mem_fun(&Window::refresh))); Canvas::do_update(); diff --git a/src/display/window.cc b/src/display/window.cc index 5107a620..ac4b704a 100644 --- a/src/display/window.cc +++ b/src/display/window.cc @@ -50,7 +50,6 @@ Window::Window(Canvas* c, bool d, int h) : m_dynamic(d), m_minHeight(h) { - m_taskUpdate.set_iterator(displayScheduler.end()); m_taskUpdate.set_slot(rak::mem_fn(this, &Window::redraw)); } diff --git a/src/display/window.h b/src/display/window.h index 7cf59ba1..99352585 100644 --- a/src/display/window.h +++ b/src/display/window.h @@ -57,7 +57,7 @@ public: bool is_active() { return m_active; } bool is_dynamic() { return m_dynamic; } - bool is_dirty() { return displayScheduler.is_scheduled(&m_taskUpdate); } + bool is_dirty() { return m_taskUpdate.is_queued(); } //utils::rak::timer get_next_draw() { return m_nextDraw; } @@ -87,13 +87,13 @@ protected: bool m_dynamic; int m_minHeight; - utils::TaskItem m_taskUpdate; + rak::priority_item m_taskUpdate; }; inline void Window::mark_dirty() { displayScheduler.erase(&m_taskUpdate); - displayScheduler.insert(&m_taskUpdate, cachedTime); + displayScheduler.push(m_taskUpdate.prepare(cachedTime)); } } diff --git a/src/display/window_download_list.cc b/src/display/window_download_list.cc index a5d66f10..79fb8bd7 100644 --- a/src/display/window_download_list.cc +++ b/src/display/window_download_list.cc @@ -60,7 +60,7 @@ WindowDownloadList::~WindowDownloadList() { void WindowDownloadList::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); m_canvas->erase(); diff --git a/src/display/window_download_statusbar.cc b/src/display/window_download_statusbar.cc index dd960d4d..34a84fab 100644 --- a/src/display/window_download_statusbar.cc +++ b/src/display/window_download_statusbar.cc @@ -54,7 +54,7 @@ WindowDownloadStatusbar::WindowDownloadStatusbar(core::Download* d) : void WindowDownloadStatusbar::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); m_canvas->erase(); diff --git a/src/display/window_file_list.cc b/src/display/window_file_list.cc index a3062790..8356d8e0 100644 --- a/src/display/window_file_list.cc +++ b/src/display/window_file_list.cc @@ -54,7 +54,7 @@ WindowFileList::WindowFileList(core::Download* d, unsigned int* focus) : void WindowFileList::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 10 * 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 10 * 1000000).round_seconds())); m_canvas->erase(); if (m_download->get_download().size_file_entries() == 0 || diff --git a/src/display/window_http_queue.cc b/src/display/window_http_queue.cc index 7458ac30..5e9a9ea6 100644 --- a/src/display/window_http_queue.cc +++ b/src/display/window_http_queue.cc @@ -58,7 +58,7 @@ WindowHttpQueue::WindowHttpQueue(core::HttpQueue* q) : void WindowHttpQueue::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); cleanup_list(); diff --git a/src/display/window_peer_info.cc b/src/display/window_peer_info.cc index 7510045d..c8df11bb 100644 --- a/src/display/window_peer_info.cc +++ b/src/display/window_peer_info.cc @@ -57,7 +57,7 @@ WindowPeerInfo::WindowPeerInfo(core::Download* d, PList* l, PList::iterator* f) void WindowPeerInfo::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); m_canvas->erase(); int y = 0; diff --git a/src/display/window_peer_list.cc b/src/display/window_peer_list.cc index 2d294af6..32410cbb 100644 --- a/src/display/window_peer_list.cc +++ b/src/display/window_peer_list.cc @@ -56,7 +56,7 @@ WindowPeerList::WindowPeerList(core::Download* d, PList* l, PList::iterator* f) void WindowPeerList::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); m_canvas->erase(); int x = 2; diff --git a/src/display/window_statusbar.cc b/src/display/window_statusbar.cc index bf12d04b..db8fce43 100644 --- a/src/display/window_statusbar.cc +++ b/src/display/window_statusbar.cc @@ -56,7 +56,7 @@ WindowStatusbar::WindowStatusbar(core::Manager* c) : void WindowStatusbar::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); m_canvas->erase(); diff --git a/src/display/window_title.cc b/src/display/window_title.cc index ab8b979f..5f3fbc89 100644 --- a/src/display/window_title.cc +++ b/src/display/window_title.cc @@ -48,7 +48,7 @@ WindowTitle::WindowTitle(const std::string& s) : void WindowTitle::redraw() { - displayScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); m_canvas->erase(); m_canvas->print(std::max(0, (m_canvas->get_width() - (int)m_title.size()) / 2 - 4), 0, diff --git a/src/display/window_tracker_list.cc b/src/display/window_tracker_list.cc index 3a4ffb17..fe1f8436 100644 --- a/src/display/window_tracker_list.cc +++ b/src/display/window_tracker_list.cc @@ -55,7 +55,7 @@ WindowTrackerList::WindowTrackerList(core::Download* d, unsigned int* focus) : void WindowTrackerList::redraw() { // TODO: Make this depend on tracker signal. - displayScheduler.insert(&m_taskUpdate, (cachedTime + 10 * 1000000).round_seconds()); + displayScheduler.push(m_taskUpdate.prepare((cachedTime + 10 * 1000000).round_seconds())); m_canvas->erase(); int pos = 0; diff --git a/src/globals.cc b/src/globals.cc index e1fa2007..7fc00a0c 100644 --- a/src/globals.cc +++ b/src/globals.cc @@ -38,6 +38,6 @@ #include "globals.h" -utils::TaskScheduler taskScheduler; -utils::TaskScheduler displayScheduler; -rak::timer cachedTime; +rak::priority_queue_default taskScheduler; +rak::priority_queue_default displayScheduler; +rak::timer cachedTime; diff --git a/src/globals.h b/src/globals.h index 52fe937d..78676f7a 100644 --- a/src/globals.h +++ b/src/globals.h @@ -38,11 +38,10 @@ #define TORRENT_GLOBALS_H #include +#include -#include "utils/task_scheduler.h" - -extern utils::TaskScheduler taskScheduler; -extern utils::TaskScheduler displayScheduler; -extern rak::timer cachedTime; +extern rak::priority_queue_default taskScheduler; +extern rak::priority_queue_default displayScheduler; +extern rak::timer cachedTime; #endif diff --git a/src/main.cc b/src/main.cc index a28fe416..58b8dfc9 100644 --- a/src/main.cc +++ b/src/main.cc @@ -220,18 +220,20 @@ main(int argc, char** argv) { countTicks++; cachedTime = rak::timer::current(); - taskScheduler.execute(cachedTime); + + std::list workQueue; + + std::copy(rak::queue_popper(taskScheduler, rak::priority_ready(cachedTime)), rak::queue_popper(), std::back_inserter(workQueue)); + std::for_each(workQueue.begin(), workQueue.end(), std::mem_fun(&rak::priority_item::clear_time)); + std::for_each(workQueue.begin(), workQueue.end(), std::mem_fun(&rak::priority_item::call)); // This needs to be called every second or so. Currently done by // the throttle task in libtorrent. - if (!displayScheduler.empty() && - displayScheduler.get_next_timeout() <= cachedTime) + if (!displayScheduler.empty() && displayScheduler.top()->time() <= cachedTime) uiControl.display()->do_update(); // Do shutdown check before poll, not after. - uiControl.core()->get_poll_manager()->poll(!taskScheduler.empty() ? - taskScheduler.get_next_timeout() - cachedTime : - 60 * 1000000); + uiControl.core()->get_poll_manager()->poll(!taskScheduler.empty() ? taskScheduler.top()->time() - cachedTime : 60 * 1000000); } uiControl.cleanup(); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 4fcf5cf6..dd9bde73 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -85,7 +85,6 @@ DownloadList::DownloadList(Control* c) : m_uiArray[DISPLAY_LOG] = new ElementLogComplete(&m_control->core()->get_log_complete()); m_windowLog = new WLog(&m_control->core()->get_log_important()); - m_taskUpdate.set_iterator(taskScheduler.end()); m_taskUpdate.set_slot(rak::mem_fn(this, &DownloadList::task_update)), setup_keys(); @@ -112,7 +111,7 @@ DownloadList::activate() { if (is_active()) throw std::logic_error("ui::Download::activate() called on an already activated object"); - taskScheduler.insert(&m_taskUpdate, cachedTime + 1000000); + taskScheduler.push(m_taskUpdate.prepare(cachedTime + 1000000)); m_windowTextInput->set_active(false); @@ -304,7 +303,7 @@ void DownloadList::task_update() { m_windowLog->receive_update(); - taskScheduler.insert(&m_taskUpdate, (cachedTime + 1000000).round_seconds()); + taskScheduler.push(m_taskUpdate.prepare((cachedTime + 1000000).round_seconds())); } void diff --git a/src/ui/download_list.h b/src/ui/download_list.h index a650827f..0c693f4b 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -138,7 +138,7 @@ private: WInput* m_windowTextInput; WHttp* m_windowHttpQueue; - utils::TaskItem m_taskUpdate; + rak::priority_item m_taskUpdate; Download* m_uiDownload; diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index c750558f..25a92f62 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -7,9 +7,6 @@ libsub_utils_a_SOURCES = \ file_stat.h \ list_focus.h \ parse.cc \ - parse.h \ - task_item.h \ - task_scheduler.cc \ - task_scheduler.h + parse.h INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) diff --git a/src/utils/task_item.h b/src/utils/task_item.h deleted file mode 100644 index 1ab69938..00000000 --- a/src/utils/task_item.h +++ /dev/null @@ -1,74 +0,0 @@ -// rTorrent - BitTorrent library -// Copyright (C) 2005, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - -#ifndef RTORRENT_UTILS_TASK_ITEM_H -#define RTORRENT_UTILS_TASK_ITEM_H - -#include -#include -#include - -namespace utils { - -// The user is responsible for removing TaskItem from the TaskScheduler. - -class TaskItem { -public: - typedef rak::function Slot; - typedef std::list >::iterator iterator; - - TaskItem() {} - - Slot& get_slot() { return m_slot; } - void set_slot(Slot s) { m_slot = s; } - - iterator get_iterator() { return m_iterator; } - const iterator get_iterator() const { return m_iterator; } - void set_iterator(iterator itr) { m_iterator = itr; } - - const rak::timer& get_time() const { return m_iterator->first; } - -private: - TaskItem(const TaskItem& t); - TaskItem& operator = (const TaskItem& t); - - iterator m_iterator; - Slot m_slot; -}; - -} - -#endif diff --git a/src/utils/task_scheduler.cc b/src/utils/task_scheduler.cc deleted file mode 100644 index 9e0fd643..00000000 --- a/src/utils/task_scheduler.cc +++ /dev/null @@ -1,93 +0,0 @@ -// rTorrent - BitTorrent library -// Copyright (C) 2005, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - -#include "config.h" - -#include - -#include "rak/functional.h" -#include "task_scheduler.h" - -namespace utils { - -void -TaskScheduler::insert(TaskItem* task, rak::timer time) { - if (is_scheduled(task)) - throw std::logic_error("TaskScheduler::insert(...) tried to insert an already inserted or invalid TaskItem"); - - // Only insert at or after m_entry because if we might be in - // execute(...). - iterator itr = std::find_if(m_entry, end(), rak::less_equal(time, rak::mem_ptr_ref(&value_type::first))); - - task->set_iterator(Base::insert(itr, value_type(time, task))); - - // Make sure m_entry points to the right node if we try inserting - // before m_entry. - if (itr == m_entry) - m_entry = task->get_iterator(); -} - -void -TaskScheduler::erase(TaskItem* task) { - if (!is_scheduled(task)) - return; - - iterator itr = Base::erase(task->get_iterator()); - - if (task->get_iterator() == m_entry) - m_entry = itr; - - task->set_iterator(end()); -} - -void -TaskScheduler::execute(rak::timer time) { - m_entry = std::find_if(begin(), end(), rak::less(time, rak::mem_ptr_ref(&value_type::first))); - - // Since we are always using the front rather than a splice of the - // due tasks, it is safe to erase them from within other tasks. - while (begin() != m_entry) { - if (!is_scheduled(Base::front().second)) - throw std::logic_error("TaskScheduler::execute_task(iterator) received an invalid iterator"); - - Base::front().second->set_iterator(end()); - Base::front().second->get_slot()(); - - Base::pop_front(); - } -} - -} diff --git a/src/utils/task_scheduler.h b/src/utils/task_scheduler.h deleted file mode 100644 index 7dc178c3..00000000 --- a/src/utils/task_scheduler.h +++ /dev/null @@ -1,78 +0,0 @@ -// rTorrent - BitTorrent library -// Copyright (C) 2005, Jari Sundell -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// In addition, as a special exception, the copyright holders give -// permission to link the code of portions of this program with the -// OpenSSL library under certain conditions as described in each -// individual source file, and distribute linked combinations -// including the two. -// -// You must obey the GNU General Public License in all respects for -// all of the code used other than OpenSSL. If you modify file(s) -// with this exception, you may extend this exception to your version -// of the file(s), but you are not obligated to do so. If you do not -// wish to do so, delete this exception statement from your version. -// If you delete this exception statement from all source files in the -// program, then also delete it here. -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - -#ifndef RTORRENT_UTILS_TASK_SCHEDULER_H -#define RTORRENT_UTILS_TASK_SCHEDULER_H - -#include "task_item.h" - -namespace utils { - -class TaskScheduler : private std::list > { -public: - typedef std::list > Base; - - using Base::value_type; - using Base::reference; - - using Base::iterator; - using Base::reverse_iterator; - using Base::size; - using Base::empty; - - using Base::begin; - using Base::end; - using Base::rbegin; - using Base::rend; - - TaskScheduler() : m_entry(begin()) {} - - void insert(TaskItem* task, rak::timer time); - void erase(TaskItem* task); - - void execute(rak::timer time); - - bool is_scheduled(const TaskItem* task) const { return task->get_iterator() != end(); } - - rak::timer get_next_timeout() const { return begin()->first; } - -private: - iterator m_entry; -}; - -} - -#endif