diff options
author | Max Kellermann <max@duempel.org> | 2014-01-04 14:56:02 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2014-01-04 15:58:59 +0100 |
commit | a357d84dce668d126fe984680e5d17f6d41b2fe6 (patch) | |
tree | a85f021ed1d7f999592f5fb3878a4b723755d1cd /src/event/DeferredMonitor.hxx | |
parent | 48c96bbaea542491b930f244e22d17db5a281434 (diff) | |
download | mpd-a357d84dce668d126fe984680e5d17f6d41b2fe6.tar.gz mpd-a357d84dce668d126fe984680e5d17f6d41b2fe6.tar.xz mpd-a357d84dce668d126fe984680e5d17f6d41b2fe6.zip |
event/DeferredMonitor: make fully thread-safe
Instead of creating a new eventfd for each DeferredMonitor instance,
reuse EventLoop's eventfd, and add a std::list to EventLoop that
manages the list of pending DeferredMonitors. This std::list is
protected by the same mutex as the "calls" list.
The bottom line is: reduced overhead because the per-instance eventfd
was eliminated, slightly added overhead due to Mutex usage (but
negligible), and we're thread-safe now.
This subsystem is now good enough to replace EventLoop::AddCall().
Diffstat (limited to 'src/event/DeferredMonitor.hxx')
-rw-r--r-- | src/event/DeferredMonitor.hxx | 43 |
1 files changed, 7 insertions, 36 deletions
diff --git a/src/event/DeferredMonitor.hxx b/src/event/DeferredMonitor.hxx index 96ad5e282..b319d25eb 100644 --- a/src/event/DeferredMonitor.hxx +++ b/src/event/DeferredMonitor.hxx @@ -23,11 +23,6 @@ #include "check.h" #include "Compiler.h" -#ifdef USE_INTERNAL_EVENTLOOP -#include "SocketMonitor.hxx" -#include "WakeFD.hxx" -#endif - #ifdef USE_GLIB_EVENTLOOP #include <glib.h> #endif @@ -39,31 +34,24 @@ class EventLoop; /** * Defer execution of an event into an #EventLoop. * - * This class is thread-safe, however the constructor must be called - * from the thread that runs the #EventLoop + * This class is thread-safe. */ -class DeferredMonitor -#ifdef USE_INTERNAL_EVENTLOOP - : private SocketMonitor -#endif -{ +class DeferredMonitor { + EventLoop &loop; + #ifdef USE_INTERNAL_EVENTLOOP - std::atomic_bool pending; - WakeFD fd; + friend class EventLoop; + bool pending; #endif #ifdef USE_GLIB_EVENTLOOP - EventLoop &loop; std::atomic<guint> source_id; #endif public: #ifdef USE_INTERNAL_EVENTLOOP DeferredMonitor(EventLoop &_loop) - :SocketMonitor(_loop), pending(false) { - SocketMonitor::Open(fd.Get()); - SocketMonitor::Schedule(SocketMonitor::READ); - } + :loop(_loop), pending(false) {} #endif #ifdef USE_GLIB_EVENTLOOP @@ -72,24 +60,11 @@ public: #endif ~DeferredMonitor() { -#ifdef USE_INTERNAL_EVENTLOOP - /* avoid closing the WakeFD twice */ - SocketMonitor::Steal(); -#endif - -#ifdef USE_GLIB_EVENTLOOP Cancel(); -#endif } EventLoop &GetEventLoop() { -#ifdef USE_INTERNAL_EVENTLOOP - return SocketMonitor::GetEventLoop(); -#endif - -#ifdef USE_GLIB_EVENTLOOP return loop; -#endif } void Schedule(); @@ -99,10 +74,6 @@ protected: virtual void RunDeferred() = 0; private: -#ifdef USE_INTERNAL_EVENTLOOP - virtual bool OnSocketReady(unsigned flags) override final; -#endif - #ifdef USE_GLIB_EVENTLOOP void Run(); static gboolean Callback(gpointer data); |