diff --git a/src/event/DeferEvent.cxx b/src/event/DeferEvent.cxx index 7e50c660d..f8bfacb28 100644 --- a/src/event/DeferEvent.cxx +++ b/src/event/DeferEvent.cxx @@ -20,14 +20,11 @@ #include "DeferEvent.hxx" #include "Loop.hxx" -void -DeferEvent::Cancel() noexcept -{ - loop.RemoveDeferred(*this); -} - void DeferEvent::Schedule() noexcept { - loop.AddDeferred(*this); + if (!IsPending()) + loop.AddDeferred(*this); + + assert(IsPending()); } diff --git a/src/event/DeferEvent.hxx b/src/event/DeferEvent.hxx index 3f5804e5b..f1914fe08 100644 --- a/src/event/DeferEvent.hxx +++ b/src/event/DeferEvent.hxx @@ -21,8 +21,7 @@ #define MPD_DEFER_EVENT_HXX #include "util/BindMethod.hxx" - -#include +#include "util/IntrusiveList.hxx" class EventLoop; @@ -34,10 +33,10 @@ class EventLoop; * This class is not thread-safe, all methods must be called from the * thread that runs the #EventLoop. */ -class DeferEvent final - : public boost::intrusive::list_base_hook<> +class DeferEvent final : AutoUnlinkIntrusiveListHook { friend class EventLoop; + friend class IntrusiveList; EventLoop &loop; @@ -51,23 +50,23 @@ public: DeferEvent(const DeferEvent &) = delete; DeferEvent &operator=(const DeferEvent &) = delete; - ~DeferEvent() noexcept { - Cancel(); - } - - EventLoop &GetEventLoop() const noexcept { + auto &GetEventLoop() const noexcept { return loop; } - void Schedule() noexcept; - void Cancel() noexcept; - -private: bool IsPending() const noexcept { return is_linked(); } - void RunDeferred() noexcept { + void Schedule() noexcept; + + void Cancel() noexcept { + if (IsPending()) + unlink(); + } + +private: + void Run() noexcept { callback(); } }; diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx index de8b4445d..2a304f950 100644 --- a/src/event/Loop.cxx +++ b/src/event/Loop.cxx @@ -198,29 +198,17 @@ EventLoop::HandleTimers() noexcept void EventLoop::AddDeferred(DeferEvent &d) noexcept { - if (d.IsPending()) - return; - - deferred.push_back(d); + defer.push_back(d); again = true; } -void -EventLoop::RemoveDeferred(DeferEvent &d) noexcept -{ - if (d.IsPending()) - deferred.erase(deferred.iterator_to(d)); -} - void EventLoop::RunDeferred() noexcept { - while (!deferred.empty() && !quit) { - auto &m = deferred.front(); - assert(m.IsPending()); - - deferred.pop_front(); - m.RunDeferred(); + while (!defer.empty() && !quit) { + defer.pop_front_and_dispose([](DeferEvent *e){ + e->Run(); + }); } } diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx index 59e4487b2..0d9868f10 100644 --- a/src/event/Loop.hxx +++ b/src/event/Loop.hxx @@ -79,11 +79,9 @@ class EventLoop final boost::intrusive::constant_time_size>; TimerSet timers; - using DeferList = - boost::intrusive::list>, - boost::intrusive::constant_time_size>; - DeferList deferred; + using DeferList = IntrusiveList; + + DeferList defer; using IdleList = IntrusiveList; IdleList idle; @@ -214,12 +212,6 @@ public: */ void AddDeferred(DeferEvent &d) noexcept; - /** - * Cancel a pending call to DeferEvent::RunDeferred(). - * However after returning, the call may still be running. - */ - void RemoveDeferred(DeferEvent &d) noexcept; - #ifdef HAVE_THREADED_EVENT_LOOP /** * Schedule a call to the InjectEvent.