summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Kellermann <max@musicpd.org>2017-08-29 14:25:23 +0200
committerMax Kellermann <max@musicpd.org>2017-08-29 14:42:59 +0200
commit010855a294b21a55355442cd6538cd46bcf80730 (patch)
treef18e576eb8dbbe77dffbd6638188c0024cec5c2d
parent71ed3ff992f2118e4d7ffe90cf186a071b129858 (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.cxx26
-rw-r--r--src/event/Loop.hxx28
-rw-r--r--src/event/TimeoutMonitor.cxx12
-rw-r--r--src/event/TimeoutMonitor.hxx15
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 */