diff options
author | Max Kellermann <max@duempel.org> | 2013-01-10 00:57:18 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2013-01-10 00:57:18 +0100 |
commit | 5c3c5066382a22b1bf19ebbcc320e222b6812bfb (patch) | |
tree | 482eb1db3aba5df012ea598db39a346993644360 /src/GlobalEvents.cxx | |
parent | ecd5eb02c5094d3160db9d92937f7011e172c254 (diff) | |
download | mpd-5c3c5066382a22b1bf19ebbcc320e222b6812bfb.tar.gz mpd-5c3c5066382a22b1bf19ebbcc320e222b6812bfb.tar.xz mpd-5c3c5066382a22b1bf19ebbcc320e222b6812bfb.zip |
GlobalEvents: lock-less operation using std::atomic
Use a bit field instead of a mutex-protected bool array.
Diffstat (limited to 'src/GlobalEvents.cxx')
-rw-r--r-- | src/GlobalEvents.cxx | 39 |
1 files changed, 8 insertions, 31 deletions
diff --git a/src/GlobalEvents.cxx b/src/GlobalEvents.cxx index a483e31b4..664803ca3 100644 --- a/src/GlobalEvents.cxx +++ b/src/GlobalEvents.cxx @@ -20,9 +20,10 @@ #include "config.h" #include "GlobalEvents.hxx" #include "event/WakeFD.hxx" -#include "thread/Mutex.hxx" #include "mpd_error.h" +#include <atomic> + #include <assert.h> #include <glib.h> #include <string.h> @@ -34,8 +35,7 @@ namespace GlobalEvents { static WakeFD wake_fd; static guint source_id; - static Mutex mutex; - static bool flags[MAX]; + static std::atomic_uint flags; static Handler handlers[MAX]; } @@ -59,15 +59,10 @@ GlobalEventCallback(G_GNUC_UNUSED GIOChannel *source, if (!GlobalEvents::wake_fd.Read()) return true; - bool events[GlobalEvents::MAX]; - GlobalEvents::mutex.lock(); - memcpy(events, GlobalEvents::flags, sizeof(events)); - memset(GlobalEvents::flags, 0, - sizeof(GlobalEvents::flags)); - GlobalEvents::mutex.unlock(); + const unsigned flags = GlobalEvents::flags.fetch_and(0); for (unsigned i = 0; i < GlobalEvents::MAX; ++i) - if (events[i]) + if (flags & (1u << i)) /* invoke the event handler */ InvokeGlobalEvent(GlobalEvents::Event(i)); @@ -113,25 +108,7 @@ GlobalEvents::Emit(Event event) { assert((unsigned)event < MAX); - mutex.lock(); - if (flags[event]) { - /* already set: don't write */ - mutex.unlock(); - return; - } - - flags[event] = true; - mutex.unlock(); - - wake_fd.Write(); -} - -void -GlobalEvents::FastEmit(Event event) -{ - assert((unsigned)event < MAX); - - flags[event] = true; - - wake_fd.Write(); + const unsigned mask = 1u << unsigned(event); + if ((GlobalEvents::flags.fetch_or(mask) & mask) == 0) + wake_fd.Write(); } |