diff --git a/configure.ac b/configure.ac index c20fc3a0..e3318936 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(rtorrent, 0.2.5, jaris@ifi.uio.no) +AC_INIT(rtorrent, 0.2.6, jaris@ifi.uio.no) AM_INIT_AUTOMAKE AM_CONFIG_HEADER(config.h) @@ -20,7 +20,7 @@ TORRENT_CHECK_EXECINFO() TORRENT_CHECK_CURL() TORRENT_OTFD() -PKG_CHECK_MODULES(STUFF, sigc++-2.0 libtorrent >= 0.6.5, +PKG_CHECK_MODULES(STUFF, sigc++-2.0 libtorrent >= 0.6.6, CXXFLAGS="$CXXFLAGS $STUFF_CFLAGS $CURL_CFLAGS"; LIBS="$LIBS $STUFF_LIBS $CURL_LIBS") diff --git a/src/main.cc b/src/main.cc index 0f2cf2d5..532e2060 100644 --- a/src/main.cc +++ b/src/main.cc @@ -45,9 +45,9 @@ #include "ui/root.h" #include "input/bindings.h" +#include "utils/task.h" #include "utils/timer.h" #include "utils/directory.h" -#include "utils/task_schedule.h" #include "signal_handler.h" #include "option_file.h" @@ -62,6 +62,10 @@ bool is_shutting_down = false; void do_panic(int signum); void print_help(); +namespace utils { + TaskScheduler taskScheduler; +} + bool is_resized() { static int x = 0; @@ -220,13 +224,15 @@ main(int argc, char** argv) { } utils::Timer::update(); - utils::TaskSchedule::perform(utils::Timer::cache()); + utils::taskScheduler.execute(utils::Timer::cache()); // This needs to be called every second or so. Currently done by // the throttle task in libtorrent. uiControl.get_display().do_update(); - uiControl.get_core().get_poll().poll(utils::TaskSchedule::get_timeout()); + uiControl.get_core().get_poll().poll(!utils::taskScheduler.empty() ? + utils::taskScheduler.get_next_timeout() - utils::Timer::cache() : + 60 * 1000000); } uiRoot.cleanup(); diff --git a/src/ui/download_list.cc b/src/ui/download_list.cc index 2fb29ee4..ee7bd7cf 100644 --- a/src/ui/download_list.cc +++ b/src/ui/download_list.cc @@ -57,24 +57,28 @@ DownloadList::DownloadList(Control* c) : m_windowStatus(new WStatus(&c->get_core())), m_windowHttpQueue(new WHttp(&c->get_core().get_http_queue())), - m_taskUpdate(sigc::mem_fun(*this, &DownloadList::task_update)), m_uiDownload(NULL), m_downloadList(&c->get_core().get_download_list()), m_control(c), - m_bindings(new input::Bindings) { - + m_bindings(new input::Bindings) +{ m_uiArray[DISPLAY_DOWNLOAD_LIST] = new ElementDownloadList(&m_downloadList); m_uiArray[DISPLAY_LOG] = new ElementLogComplete(&m_control->get_core().get_log_complete()); - m_windowLog = new WLog(&m_control->get_core().get_log_important()); + m_taskUpdate.set_iterator(utils::taskScheduler.end()); + m_taskUpdate.set_slot(sigc::mem_fun(*this, &DownloadList::task_update)), + setup_keys(); setup_input(); } DownloadList::~DownloadList() { + if (m_window != m_control->get_display().end()) + throw std::logic_error("ui::DownloadList::~DownloadList() called on an active object"); + std::for_each(m_uiArray, m_uiArray + DISPLAY_MAX_SIZE, rak::call_delete()); delete m_windowTitle; @@ -92,7 +96,7 @@ DownloadList::activate() { if (m_window != m_control->get_display().end()) throw std::logic_error("ui::Download::activate() called on an already activated object"); - m_taskUpdate.insert(utils::Timer::cache() + 1000000); + utils::taskScheduler.insert(&m_taskUpdate, utils::Timer::cache() + 1000000); m_windowTextInput->set_active(false); @@ -116,7 +120,7 @@ DownloadList::disable() { disable_display(); - m_taskUpdate.remove(); + utils::taskScheduler.erase(&m_taskUpdate); if (m_windowTextInput->is_active()) { m_windowTextInput->get_input()->clear(); @@ -284,7 +288,7 @@ void DownloadList::task_update() { m_windowLog->receive_update(); - m_taskUpdate.insert(utils::Timer::cache() + 1000000); + utils::taskScheduler.insert(&m_taskUpdate, (utils::Timer::cache() + 1000000).round_seconds()); } void diff --git a/src/ui/download_list.h b/src/ui/download_list.h index 691868a0..f4a48b16 100644 --- a/src/ui/download_list.h +++ b/src/ui/download_list.h @@ -125,7 +125,7 @@ private: WInput* m_windowTextInput; WHttp* m_windowHttpQueue; - utils::Task m_taskUpdate; + utils::TaskItem m_taskUpdate; Download* m_uiDownload; diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 4b331975..978de3c0 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -9,8 +9,9 @@ libsub_utils_a_SOURCES = \ parse.cc \ parse.h \ task.h \ - task_schedule.cc \ - task_schedule.h \ + task_item.h \ + task_scheduler.cc \ + task_scheduler.h \ timer.h INCLUDES = -I$(srcdir) -I$(srcdir)/.. -I$(top_srcdir) diff --git a/src/utils/task.h b/src/utils/task.h index 355f36e6..366ba11d 100644 --- a/src/utils/task.h +++ b/src/utils/task.h @@ -1,4 +1,4 @@ -// rTorrent - BitTorrent client +// rTorrent - BitTorrent library // Copyright (C) 2005, Jari Sundell // // This program is free software; you can redistribute it and/or modify @@ -23,56 +23,12 @@ #ifndef RTORRENT_UTILS_TASK_H #define RTORRENT_UTILS_TASK_H -#include - -#include "timer.h" -#include "task_schedule.h" +#include "task_scheduler.h" namespace utils { - -class Task { -public: - typedef sigc::slot Slot; - - Task(Slot s = Slot()) : m_slot(s) { clear_iterator(); } - ~Task() { remove(); } - - bool is_scheduled() { return m_itr != TaskSchedule::end(); } - - void set_slot(Slot s) { m_slot = s; } - Slot& get_slot() { return m_slot; } - - Timer get_time() { return m_time; } - - void insert(Timer t) { - remove(); - - m_time = t; - m_itr = TaskSchedule::insert(this); - } - - void remove() { - if (m_itr != TaskSchedule::end()) { - TaskSchedule::erase(m_itr); - clear_iterator(); - } - } - -protected: - friend class TaskSchedule; - - TaskSchedule::iterator get_iterator() { return m_itr; } - void clear_iterator() { m_itr = TaskSchedule::end(); } - -private: - Task(const Task&); - void operator () (const Task&); - - Timer m_time; - TaskSchedule::iterator m_itr; - Slot m_slot; -}; - + +extern TaskScheduler taskScheduler; + } #endif diff --git a/src/utils/task_item.h b/src/utils/task_item.h new file mode 100644 index 00000000..b57c008e --- /dev/null +++ b/src/utils/task_item.h @@ -0,0 +1,60 @@ +// 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 +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#ifndef RTORRENT_UTILS_TASK_ITEM_H +#define RTORRENT_UTILS_TASK_ITEM_H + +#include +#include + +#include "utils/timer.h" + +namespace utils { + +// The user is responsible for removing TaskItem from the TaskScheduler. + +class TaskItem { +public: + typedef sigc::slot Slot; + typedef std::list >::iterator iterator; + + TaskItem(Slot s = Slot()) : m_slot(s) {} + + Slot& get_slot() { return m_slot; } + void set_slot(Slot s) { m_slot = s; } + + iterator get_iterator() { return m_iterator; } + void set_iterator(iterator itr) { m_iterator = itr; } + + const Timer& get_time() { 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_schedule.cc b/src/utils/task_schedule.cc deleted file mode 100644 index 6230e7b1..00000000 --- a/src/utils/task_schedule.cc +++ /dev/null @@ -1,76 +0,0 @@ -// rTorrent - BitTorrent client -// 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 -// -// Contact: Jari Sundell -// -// Skomakerveien 33 -// 3185 Skoppum, NORWAY - -#include "config.h" - -#include -#include - -#include "task.h" -#include "task_schedule.h" - -namespace utils { - -TaskSchedule::Container TaskSchedule::m_container; - -// Remove this, replace with stuff. -struct task_comp { - task_comp(Timer t) : m_time(t) {} - - bool operator () (Task* t) { - return m_time <= t->get_time(); - } - - Timer m_time; -}; - -inline void -TaskSchedule::execute_task(Task* t) { - t->clear_iterator(); - t->get_slot()(); -} - -void -TaskSchedule::perform(Timer t) { - Container c; - - c.splice(c.begin(), c, m_container.begin(), std::find_if(m_container.begin(), m_container.end(), task_comp(t))); - - std::for_each(c.begin(), c.end(), std::ptr_fun(&TaskSchedule::execute_task)); -} - -Timer -TaskSchedule::get_timeout() { - if (!m_container.empty()) - return std::max(m_container.front()->get_time() - Timer::current(), Timer()); - else - return Timer((int64_t)(1 << 30) * 1000000); -} - -TaskSchedule::iterator -TaskSchedule::insert(Task* t) { - iterator itr = std::find_if(m_container.begin(), m_container.end(), task_comp(t->get_time())); - - return m_container.insert(itr, t); -} - -} diff --git a/src/utils/task_scheduler.cc b/src/utils/task_scheduler.cc new file mode 100644 index 00000000..d4db5d55 --- /dev/null +++ b/src/utils/task_scheduler.cc @@ -0,0 +1,72 @@ +// 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 +// +// Contact: Jari Sundell +// +// Skomakerveien 33 +// 3185 Skoppum, NORWAY + +#include "config.h" + +#include + +#include "rak/functional.h" +#include "task_scheduler.h" + +namespace utils { + +inline void +TaskScheduler::execute_task(const value_type& v) { + if (!is_scheduled(v.second)) + throw std::logic_error("TaskScheduler::execute_task(iterator) received an invalid iterator"); + + v.second->set_iterator(end()); + v.second->get_slot()(); +} + +void +TaskScheduler::insert(TaskItem* task, Timer time) { + if (is_scheduled(task)) + throw std::logic_error("TaskScheduler::insert(...) tried to insert an already inserted or invalid TaskItem"); + + iterator itr = std::find_if(begin(), end(), + rak::less_equal(time, rak::mem_ptr_ref(&value_type::first))); + + task->set_iterator(Base::insert(itr, value_type(time, task))); +} + +void +TaskScheduler::erase(TaskItem* task) { + if (!is_scheduled(task)) + return; + + Base::erase(task->get_iterator()); + task->set_iterator(end()); +} + +void +TaskScheduler::execute(Timer time) { + Base tmp; + + tmp.splice(tmp.begin(), *this, + begin(), std::find_if(begin(), end(), rak::less_equal(time, rak::mem_ptr_ref(&value_type::first)))); + + std::for_each(tmp.begin(), tmp.end(), + rak::bind1st(std::mem_fun(&TaskScheduler::execute_task), this)); +} + +} diff --git a/src/utils/task_schedule.h b/src/utils/task_scheduler.h similarity index 51% rename from src/utils/task_schedule.h rename to src/utils/task_scheduler.h index 01569e9d..41a87e91 100644 --- a/src/utils/task_schedule.h +++ b/src/utils/task_scheduler.h @@ -1,4 +1,4 @@ -// rTorrent - BitTorrent client +// rTorrent - BitTorrent library // Copyright (C) 2005, Jari Sundell // // This program is free software; you can redistribute it and/or modify @@ -20,38 +20,41 @@ // Skomakerveien 33 // 3185 Skoppum, NORWAY -#ifndef RTORRENT_UTILS_TASK_SCHEDULE_H -#define RTORRENT_UTILS_TASK_SCHEDULE_H +#ifndef RTORRENT_UTILS_TASK_SCHEDULER_H +#define RTORRENT_UTILS_TASK_SCHEDULER_H -#include - -#include "timer.h" +#include "task_item.h" namespace utils { -class Task; - -class TaskSchedule { +class TaskScheduler : private std::list > { public: - friend class Task; + typedef std::list > Base; - typedef std::list Container; - typedef Container::iterator iterator; + using Base::value_type; + using Base::reference; - static void perform(Timer t); + using Base::iterator; + using Base::reverse_iterator; + using Base::size; + using Base::empty; - static Timer get_timeout(); + using Base::begin; + using Base::end; + using Base::rbegin; + using Base::rend; -protected: - static iterator end() { return m_container.end(); } + void insert(TaskItem* task, Timer time); + void erase(TaskItem* task); - static iterator insert(Task* t); - static void erase(iterator itr) { m_container.erase(itr); } + void execute(Timer time); + + bool is_scheduled(TaskItem* task) { return task->get_iterator() != end(); } + + Timer get_next_timeout() const { return begin()->first; } private: - static inline void execute_task(Task* t); - - static Container m_container; + inline void execute_task(const value_type& v); }; }