From e52ac0b187bc822eb45d5589e1d9637a348e7a54 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 5 Mar 2016 18:49:42 +0100 Subject: [PATCH] event/MaskMonitor: new class to replace code in GlobalEvents and Idle --- Makefile.am | 1 + src/GlobalEvents.cxx | 18 +++++-------- src/event/MaskMonitor.cxx | 36 ++++++++++++++++++++++++++ src/event/MaskMonitor.hxx | 53 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 src/event/MaskMonitor.cxx create mode 100644 src/event/MaskMonitor.hxx diff --git a/Makefile.am b/Makefile.am index 3d393b5bf..77b631f40 100644 --- a/Makefile.am +++ b/Makefile.am @@ -490,6 +490,7 @@ libevent_a_SOURCES = \ src/event/TimeoutMonitor.hxx src/event/TimeoutMonitor.cxx \ src/event/IdleMonitor.hxx src/event/IdleMonitor.cxx \ src/event/DeferredMonitor.hxx src/event/DeferredMonitor.cxx \ + src/event/MaskMonitor.hxx src/event/MaskMonitor.cxx \ src/event/SocketMonitor.cxx src/event/SocketMonitor.hxx \ src/event/BufferedSocket.cxx src/event/BufferedSocket.hxx \ src/event/FullyBufferedSocket.cxx src/event/FullyBufferedSocket.hxx \ diff --git a/src/GlobalEvents.cxx b/src/GlobalEvents.cxx index 5d6c7b992..3cdafdd29 100644 --- a/src/GlobalEvents.cxx +++ b/src/GlobalEvents.cxx @@ -20,24 +20,21 @@ #include "config.h" #include "GlobalEvents.hxx" #include "util/Manual.hxx" -#include "event/DeferredMonitor.hxx" - -#include +#include "event/MaskMonitor.hxx" #include namespace GlobalEvents { - class Monitor final : public DeferredMonitor { + class Monitor final : public MaskMonitor { public: - Monitor(EventLoop &_loop):DeferredMonitor(_loop) {} + explicit Monitor(EventLoop &_loop):MaskMonitor(_loop) {} protected: - virtual void RunDeferred() override; + virtual void HandleMask(unsigned mask) override; }; static Manual monitor; - static std::atomic_uint flags; static Handler handlers[MAX]; } @@ -54,10 +51,8 @@ InvokeGlobalEvent(GlobalEvents::Event event) } void -GlobalEvents::Monitor::RunDeferred() +GlobalEvents::Monitor::HandleMask(unsigned f) { - const unsigned f = flags.exchange(0); - for (unsigned i = 0; i < MAX; ++i) if (f & (1u << i)) /* invoke the event handler */ @@ -91,6 +86,5 @@ GlobalEvents::Emit(Event event) assert((unsigned)event < MAX); const unsigned mask = 1u << unsigned(event); - if (GlobalEvents::flags.fetch_or(mask) == 0) - monitor->Schedule(); + monitor->OrMask(mask); } diff --git a/src/event/MaskMonitor.cxx b/src/event/MaskMonitor.cxx new file mode 100644 index 000000000..ff9cb9d47 --- /dev/null +++ b/src/event/MaskMonitor.cxx @@ -0,0 +1,36 @@ +/* + * Copyright 2003-2016 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include "MaskMonitor.hxx" + +void +MaskMonitor::OrMask(unsigned new_mask) +{ + if (pending_mask.fetch_or(new_mask) == 0) + DeferredMonitor::Schedule(); +} + +void +MaskMonitor::RunDeferred() +{ + const unsigned mask = pending_mask.exchange(0); + if (mask != 0) + HandleMask(mask); +} diff --git a/src/event/MaskMonitor.hxx b/src/event/MaskMonitor.hxx new file mode 100644 index 000000000..db6803bbf --- /dev/null +++ b/src/event/MaskMonitor.hxx @@ -0,0 +1,53 @@ +/* + * Copyright 2003-2016 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_EVENT_MASK_MONITOR_HXX +#define MPD_EVENT_MASK_MONITOR_HXX + +#include "check.h" +#include "DeferredMonitor.hxx" + +#include + +/** + * Manage a bit mask of events that have occurred. Every time the + * mask becomes non-zero, OnMask() is called in #EventLoop's thread. + * + * This class is thread-safe. + */ +class MaskMonitor : DeferredMonitor { + std::atomic_uint pending_mask; + +public: + explicit MaskMonitor(EventLoop &_loop) + :DeferredMonitor(_loop), pending_mask(0) {} + + using DeferredMonitor::GetEventLoop; + using DeferredMonitor::Cancel; + + void OrMask(unsigned new_mask); + +protected: + virtual void HandleMask(unsigned mask) = 0; + + /* virtual methode from class DeferredMonitor */ + void RunDeferred() override; +}; + +#endif