diff --git a/src/event/DeferredMonitor.hxx b/src/event/DeferredMonitor.hxx index 09815dfc9..917c06385 100644 --- a/src/event/DeferredMonitor.hxx +++ b/src/event/DeferredMonitor.hxx @@ -22,6 +22,8 @@ #include "check.h" +#include + class EventLoop; /** @@ -30,14 +32,16 @@ class EventLoop; * This class is thread-safe. */ class DeferredMonitor { - EventLoop &loop; - friend class EventLoop; - bool pending; + + typedef boost::intrusive::list_member_hook<> ListHook; + ListHook list_hook; + + EventLoop &loop; public: DeferredMonitor(EventLoop &_loop) - :loop(_loop), pending(false) {} + :loop(_loop) {} ~DeferredMonitor() { Cancel(); @@ -50,8 +54,13 @@ public: void Schedule(); void Cancel(); +private: + bool IsPending() const { + return list_hook.is_linked(); + } + protected: virtual void RunDeferred() = 0; }; -#endif /* MAIN_NOTIFY_H */ +#endif diff --git a/src/event/IdleMonitor.cxx b/src/event/IdleMonitor.cxx index d39b96e87..1e3c2ea3a 100644 --- a/src/event/IdleMonitor.cxx +++ b/src/event/IdleMonitor.cxx @@ -31,7 +31,6 @@ IdleMonitor::Cancel() if (!IsActive()) return; - active = false; loop.RemoveIdle(*this); } @@ -44,7 +43,6 @@ IdleMonitor::Schedule() /* already scheduled */ return; - active = true; loop.AddIdle(*this); } @@ -53,8 +51,5 @@ IdleMonitor::Run() { assert(loop.IsInside()); - assert(active); - active = false; - OnIdle(); } diff --git a/src/event/IdleMonitor.hxx b/src/event/IdleMonitor.hxx index 9b7ab5276..2926717e9 100644 --- a/src/event/IdleMonitor.hxx +++ b/src/event/IdleMonitor.hxx @@ -22,6 +22,8 @@ #include "check.h" +#include + class EventLoop; /** @@ -35,13 +37,14 @@ class EventLoop; class IdleMonitor { friend class EventLoop; - EventLoop &loop; + typedef boost::intrusive::list_member_hook<> ListHook; + ListHook list_hook; - bool active; + EventLoop &loop; public: IdleMonitor(EventLoop &_loop) - :loop(_loop), active(false) {} + :loop(_loop) {} ~IdleMonitor() { #ifndef NDEBUG @@ -57,7 +60,7 @@ public: } bool IsActive() const { - return active; + return list_hook.is_linked(); } void Schedule(); diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx index 3f01e6ef8..a8fa507cd 100644 --- a/src/event/Loop.cxx +++ b/src/event/Loop.cxx @@ -24,8 +24,6 @@ #include "DeferredMonitor.hxx" #include "util/ScopeExit.hxx" -#include - EventLoop::EventLoop(ThreadId _thread) :SocketMonitor(*this), thread(_thread) { @@ -70,9 +68,8 @@ void EventLoop::AddIdle(IdleMonitor &i) { assert(IsInside()); - assert(std::find(idle.begin(), idle.end(), &i) == idle.end()); - idle.push_back(&i); + idle.push_back(i); again = true; } @@ -81,10 +78,7 @@ EventLoop::RemoveIdle(IdleMonitor &i) { assert(IsInside()); - auto it = std::find(idle.begin(), idle.end(), &i); - assert(it != idle.end()); - - idle.erase(it); + idle.erase(idle.iterator_to(i)); } void @@ -161,7 +155,7 @@ EventLoop::Run() /* invoke idle */ while (!idle.empty()) { - IdleMonitor &m = *idle.front(); + IdleMonitor &m = idle.front(); idle.pop_front(); m.Run(); @@ -223,18 +217,14 @@ EventLoop::AddDeferred(DeferredMonitor &d) { const std::lock_guard lock(mutex); - if (d.pending) + if (d.IsPending()) return; - assert(std::find(deferred.begin(), - deferred.end(), &d) == deferred.end()); - /* we don't need to wake up the EventLoop if another DeferredMonitor has already done it */ must_wake = !busy && deferred.empty(); - d.pending = true; - deferred.push_back(&d); + deferred.push_back(d); again = true; } @@ -247,29 +237,18 @@ EventLoop::RemoveDeferred(DeferredMonitor &d) { const std::lock_guard protect(mutex); - if (!d.pending) { - assert(std::find(deferred.begin(), - deferred.end(), &d) == deferred.end()); - return; - } - - d.pending = false; - - auto i = std::find(deferred.begin(), deferred.end(), &d); - assert(i != deferred.end()); - - deferred.erase(i); + if (!d.IsPending()) + deferred.erase(deferred.iterator_to(d)); } void EventLoop::HandleDeferred() { while (!deferred.empty() && !quit) { - DeferredMonitor &m = *deferred.front(); - assert(m.pending); + DeferredMonitor &m = deferred.front(); + assert(m.IsPending()); deferred.pop_front(); - m.pending = false; const ScopeUnlock unlock(mutex); m.RunDeferred(); diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx index 6e3d38ea4..67da1c5a6 100644 --- a/src/event/Loop.hxx +++ b/src/event/Loop.hxx @@ -29,16 +29,13 @@ #include "WakeFD.hxx" #include "SocketMonitor.hxx" #include "TimeoutMonitor.hxx" +#include "IdleMonitor.hxx" +#include "DeferredMonitor.hxx" #include +#include #include -#include -#include - -class TimeoutMonitor; -class IdleMonitor; -class DeferredMonitor; #include @@ -70,10 +67,21 @@ class EventLoop final : SocketMonitor boost::intrusive::constant_time_size> TimerSet; TimerSet timers; - std::list idle; + typedef boost::intrusive::list, + boost::intrusive::constant_time_size> IdleList; + IdleList idle; Mutex mutex; - std::list deferred; + + typedef boost::intrusive::list, + boost::intrusive::constant_time_size> DeferredList; + DeferredList deferred; std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();