diff options
author | Max Kellermann <max@musicpd.org> | 2017-08-29 14:25:23 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2017-08-29 14:42:59 +0200 |
commit | 010855a294b21a55355442cd6538cd46bcf80730 (patch) | |
tree | f18e576eb8dbbe77dffbd6638188c0024cec5c2d | |
parent | 71ed3ff992f2118e4d7ffe90cf186a071b129858 (diff) |
event/Loop: use boost::intrusive::multiset to store TimeoutMonitors
By using an "intrusive" data structure, we can easily eliminate
struct TimerRecord.
-rw-r--r-- | src/event/Loop.cxx | 26 | ||||
-rw-r--r-- | src/event/Loop.hxx | 28 | ||||
-rw-r--r-- | src/event/TimeoutMonitor.cxx | 12 | ||||
-rw-r--r-- | src/event/TimeoutMonitor.hxx | 15 |
4 files changed, 31 insertions, 50 deletions
diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx index 5a9be77e7..3f01e6ef8 100644 --- a/src/event/Loop.cxx +++ b/src/event/Loop.cxx @@ -19,7 +19,6 @@ #include "config.h" #include "Loop.hxx" -#include "TimeoutMonitor.hxx" #include "SocketMonitor.hxx" #include "IdleMonitor.hxx" #include "DeferredMonitor.hxx" @@ -27,18 +26,6 @@ #include <algorithm> -inline std::chrono::steady_clock::time_point -EventLoop::TimerRecord::GetDue() const noexcept -{ - return timer.due; -} - -inline bool -EventLoop::TimerRecord::operator<(const TimerRecord &other) const noexcept -{ - return timer.due < other.timer.due; -} - EventLoop::EventLoop(ThreadId _thread) :SocketMonitor(*this), thread(_thread) { @@ -106,7 +93,7 @@ EventLoop::AddTimer(TimeoutMonitor &t, std::chrono::steady_clock::duration d) assert(IsInside()); t.due = now + d; - timers.insert(TimerRecord(t)); + timers.insert(t); again = true; } @@ -115,12 +102,7 @@ EventLoop::CancelTimer(TimeoutMonitor &t) { assert(IsInside()); - for (auto i = timers.begin(), end = timers.end(); i != end; ++i) { - if (&i->timer == &t) { - timers.erase(i); - return; - } - } + timers.erase(timers.iterator_to(t)); } /** @@ -163,11 +145,11 @@ EventLoop::Run() break; } - timeout = i->GetDue() - now; + TimeoutMonitor &m = *i; + timeout = m.due - now; if (timeout > timeout.zero()) break; - TimeoutMonitor &m = i->timer; timers.erase(i); m.Run(); diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx index 2e1b6274c..6e3d38ea4 100644 --- a/src/event/Loop.hxx +++ b/src/event/Loop.hxx @@ -28,6 +28,9 @@ #include "thread/Mutex.hxx" #include "WakeFD.hxx" #include "SocketMonitor.hxx" +#include "TimeoutMonitor.hxx" + +#include <boost/intrusive/set.hpp> #include <chrono> #include <list> @@ -50,22 +53,23 @@ class DeferredMonitor; */ class EventLoop final : SocketMonitor { - struct TimerRecord { - TimeoutMonitor &timer; - - explicit constexpr TimerRecord(TimeoutMonitor &_timer) - :timer(_timer) {} - - gcc_pure - std::chrono::steady_clock::time_point GetDue() const noexcept; + WakeFD wake_fd; - gcc_pure - bool operator<(const TimerRecord &other) const noexcept; + struct TimerCompare { + constexpr bool operator()(const TimeoutMonitor &a, + const TimeoutMonitor &b) const { + return a.due < b.due; + } }; - WakeFD wake_fd; + typedef boost::intrusive::multiset<TimeoutMonitor, + boost::intrusive::member_hook<TimeoutMonitor, + TimeoutMonitor::TimerSetHook, + &TimeoutMonitor::timer_set_hook>, + boost::intrusive::compare<TimerCompare>, + boost::intrusive::constant_time_size<false>> TimerSet; + TimerSet timers; - std::multiset<TimerRecord> timers; std::list<IdleMonitor *> idle; Mutex mutex; diff --git a/src/event/TimeoutMonitor.cxx b/src/event/TimeoutMonitor.cxx index 223c08b1a..b2c14559b 100644 --- a/src/event/TimeoutMonitor.cxx +++ b/src/event/TimeoutMonitor.cxx @@ -24,10 +24,8 @@ void TimeoutMonitor::Cancel() { - if (IsActive()) { - active = false; + if (IsActive()) loop.CancelTimer(*this); - } } void @@ -35,13 +33,5 @@ TimeoutMonitor::Schedule(std::chrono::steady_clock::duration d) { Cancel(); - active = true; loop.AddTimer(*this, d); } - -void -TimeoutMonitor::Run() -{ - active = false; - OnTimeout(); -} diff --git a/src/event/TimeoutMonitor.hxx b/src/event/TimeoutMonitor.hxx index f29fbd8af..ddb46edf0 100644 --- a/src/event/TimeoutMonitor.hxx +++ b/src/event/TimeoutMonitor.hxx @@ -22,6 +22,8 @@ #include "check.h" +#include <boost/intrusive/set_hook.hpp> + #include <chrono> class EventLoop; @@ -37,6 +39,9 @@ class EventLoop; class TimeoutMonitor { friend class EventLoop; + typedef boost::intrusive::set_member_hook<> TimerSetHook; + TimerSetHook timer_set_hook; + EventLoop &loop; /** @@ -45,11 +50,9 @@ class TimeoutMonitor { */ std::chrono::steady_clock::time_point due; - bool active; - public: TimeoutMonitor(EventLoop &_loop) - :loop(_loop), active(false) { + :loop(_loop) { } ~TimeoutMonitor() { @@ -61,7 +64,7 @@ public: } bool IsActive() const { - return active; + return timer_set_hook.is_linked(); } void Schedule(std::chrono::steady_clock::duration d); @@ -71,7 +74,9 @@ protected: virtual void OnTimeout() = 0; private: - void Run(); + void Run() { + OnTimeout(); + } }; #endif /* MAIN_NOTIFY_H */ |