GlobalEvents: lock-less operation using std::atomic
Use a bit field instead of a mutex-protected bool array.
This commit is contained in:
parent
ecd5eb02c5
commit
5c3c506638
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -58,13 +58,6 @@ namespace GlobalEvents {
|
|||
void Register(Event event, Handler handler);
|
||||
|
||||
void Emit(Event event);
|
||||
|
||||
/**
|
||||
* Similar to event_pipe_emit(), but aimed for use in signal handlers:
|
||||
* it doesn't lock the mutex, and doesn't log on error. That makes it
|
||||
* potentially lossy, but for its intended use, that does not matter.
|
||||
*/
|
||||
void FastEmit(Event event);
|
||||
}
|
||||
|
||||
#endif /* MAIN_NOTIFY_H */
|
||||
|
|
|
@ -40,7 +40,7 @@ static void exit_signal_handler(G_GNUC_UNUSED int signum)
|
|||
|
||||
static void reload_signal_handler(G_GNUC_UNUSED int signum)
|
||||
{
|
||||
GlobalEvents::FastEmit(GlobalEvents::RELOAD);
|
||||
GlobalEvents::Emit(GlobalEvents::RELOAD);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Reference in New Issue