From 30a5dd267b6cb9ee21106d5d949de2f04781c6e7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 29 Aug 2017 15:53:57 +0200 Subject: [PATCH] event/TimeoutMonitor: move code to new class TimerEvent --- Makefile.am | 3 +- src/event/Loop.cxx | 10 +-- src/event/Loop.hxx | 20 ++--- src/event/TimeoutMonitor.hxx | 33 +++----- .../{TimeoutMonitor.cxx => TimerEvent.cxx} | 6 +- src/event/TimerEvent.hxx | 83 +++++++++++++++++++ 6 files changed, 115 insertions(+), 40 deletions(-) rename src/event/{TimeoutMonitor.cxx => TimerEvent.cxx} (88%) create mode 100644 src/event/TimerEvent.hxx diff --git a/Makefile.am b/Makefile.am index cd1311029..19d331836 100644 --- a/Makefile.am +++ b/Makefile.am @@ -514,7 +514,8 @@ libevent_a_SOURCES = \ src/event/PollGroupWinSelect.hxx src/event/PollGroupWinSelect.cxx \ src/event/PollResultGeneric.hxx \ src/event/SignalMonitor.hxx src/event/SignalMonitor.cxx \ - src/event/TimeoutMonitor.hxx src/event/TimeoutMonitor.cxx \ + src/event/TimerEvent.hxx src/event/TimerEvent.cxx \ + src/event/TimeoutMonitor.hxx \ src/event/IdleMonitor.hxx src/event/IdleMonitor.cxx \ src/event/DeferredMonitor.hxx src/event/DeferredMonitor.cxx \ src/event/DeferredCall.hxx \ diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx index de3879fc1..e3ea891c4 100644 --- a/src/event/Loop.cxx +++ b/src/event/Loop.cxx @@ -82,7 +82,7 @@ EventLoop::RemoveIdle(IdleMonitor &i) } void -EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d) +EventLoop::AddTimer(TimerEvent &t, std::chrono::steady_clock::duration d) { assert(IsInside()); @@ -92,7 +92,7 @@ EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d) } void -EventLoop::CancelTimer(TimeoutMonitor &t) +EventLoop::CancelTimer(TimerEvent &t) { assert(IsInside()); @@ -139,14 +139,14 @@ EventLoop::Run() break; } - TimeoutMonitor &m = *i; - timeout = m.due - now; + TimerEvent &t = *i; + timeout = t.due - now; if (timeout > timeout.zero()) break; timers.erase(i); - m.Run(); + t.Run(); if (quit) return; diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx index 67da1c5a6..b76f4a762 100644 --- a/src/event/Loop.hxx +++ b/src/event/Loop.hxx @@ -28,7 +28,7 @@ #include "thread/Mutex.hxx" #include "WakeFD.hxx" #include "SocketMonitor.hxx" -#include "TimeoutMonitor.hxx" +#include "TimerEvent.hxx" #include "IdleMonitor.hxx" #include "DeferredMonitor.hxx" @@ -46,23 +46,23 @@ * thread that runs it, except where explicitly documented as * thread-safe. * - * @see SocketMonitor, MultiSocketMonitor, TimeoutMonitor, IdleMonitor + * @see SocketMonitor, MultiSocketMonitor, TimerEvent, IdleMonitor */ class EventLoop final : SocketMonitor { WakeFD wake_fd; struct TimerCompare { - constexpr bool operator()(const TimeoutMonitor &a, - const TimeoutMonitor &b) const { + constexpr bool operator()(const TimerEvent &a, + const TimerEvent &b) const { return a.due < b.due; } }; - typedef boost::intrusive::multiset, + typedef boost::intrusive::multiset, boost::intrusive::compare, boost::intrusive::constant_time_size> TimerSet; TimerSet timers; @@ -155,9 +155,9 @@ public: void AddIdle(IdleMonitor &i); void RemoveIdle(IdleMonitor &i); - void AddTimer(TimeoutMonitor &t, + void AddTimer(TimerEvent &t, std::chrono::steady_clock::duration d); - void CancelTimer(TimeoutMonitor &t); + void CancelTimer(TimerEvent &t); /** * Schedule a call to DeferredMonitor::RunDeferred(). diff --git a/src/event/TimeoutMonitor.hxx b/src/event/TimeoutMonitor.hxx index ddb46edf0..59677aa8d 100644 --- a/src/event/TimeoutMonitor.hxx +++ b/src/event/TimeoutMonitor.hxx @@ -21,6 +21,7 @@ #define MPD_SOCKET_TIMEOUT_MONITOR_HXX #include "check.h" +#include "TimerEvent.hxx" #include @@ -37,38 +38,28 @@ class EventLoop; * as thread-safe. */ class TimeoutMonitor { - friend class EventLoop; - - typedef boost::intrusive::set_member_hook<> TimerSetHook; - TimerSetHook timer_set_hook; - - EventLoop &loop; - - /** - * When is this timer due? This is only valid if #active is - * true. - */ - std::chrono::steady_clock::time_point due; + TimerEvent timer; public: TimeoutMonitor(EventLoop &_loop) - :loop(_loop) { - } - - ~TimeoutMonitor() { - Cancel(); + :timer(_loop, BIND_THIS_METHOD(Run)) { } EventLoop &GetEventLoop() { - return loop; + return timer.GetEventLoop(); } bool IsActive() const { - return timer_set_hook.is_linked(); + return timer.IsActive(); } - void Schedule(std::chrono::steady_clock::duration d); - void Cancel(); + void Schedule(std::chrono::steady_clock::duration d) { + timer.Schedule(d); + } + + void Cancel() { + timer.Cancel(); + } protected: virtual void OnTimeout() = 0; diff --git a/src/event/TimeoutMonitor.cxx b/src/event/TimerEvent.cxx similarity index 88% rename from src/event/TimeoutMonitor.cxx rename to src/event/TimerEvent.cxx index b2c14559b..0943d8a34 100644 --- a/src/event/TimeoutMonitor.cxx +++ b/src/event/TimerEvent.cxx @@ -18,18 +18,18 @@ */ #include "config.h" -#include "TimeoutMonitor.hxx" +#include "TimerEvent.hxx" #include "Loop.hxx" void -TimeoutMonitor::Cancel() +TimerEvent::Cancel() { if (IsActive()) loop.CancelTimer(*this); } void -TimeoutMonitor::Schedule(std::chrono::steady_clock::duration d) +TimerEvent::Schedule(std::chrono::steady_clock::duration d) { Cancel(); diff --git a/src/event/TimerEvent.hxx b/src/event/TimerEvent.hxx new file mode 100644 index 000000000..55d2ce4c8 --- /dev/null +++ b/src/event/TimerEvent.hxx @@ -0,0 +1,83 @@ +/* + * Copyright 2003-2017 The Music Player Daemon Project + * http://www.musicpd.org + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_TIMER_EVENT_HXX +#define MPD_TIMER_EVENT_HXX + +#include "check.h" +#include "util/BindMethod.hxx" + +#include + +#include + +class EventLoop; + +/** + * This class invokes a callback function after a certain amount of + * time. Use Schedule() to start the timer or Cancel() to cancel it. + * + * This class is not thread-safe, all methods must be called from the + * thread that runs the #EventLoop, except where explicitly documented + * as thread-safe. + */ +class TimerEvent final { + friend class EventLoop; + + typedef boost::intrusive::set_member_hook<> TimerSetHook; + TimerSetHook timer_set_hook; + + EventLoop &loop; + + typedef BoundMethod Callback; + const Callback callback; + + /** + * When is this timer due? This is only valid if IsActive() + * returns true. + */ + std::chrono::steady_clock::time_point due; + +public: + TimerEvent(EventLoop &_loop, Callback _callback) + :loop(_loop), callback(_callback) { + } + + ~TimerEvent() { + Cancel(); + } + + EventLoop &GetEventLoop() { + return loop; + } + + bool IsActive() const { + return timer_set_hook.is_linked(); + } + + void Schedule(std::chrono::steady_clock::duration d); + void Cancel(); + +private: + void Run() { + callback(); + } +}; + +#endif /* MAIN_NOTIFY_H */