aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Krjuchkov <denis@crazydev.net>2013-11-27 17:04:38 +0600
committerDenis Krjuchkov <denis@crazydev.net>2013-11-27 17:28:36 +0600
commit46bab7e4b921b79924643bacd08dcd3d1404ceb6 (patch)
tree2fe8e1b2185dba89d953b5d02f22cc0781e17c2c
parent22fb49fa90241abfaf5ac81de462f4b2c274f7d0 (diff)
downloadmpd-46bab7e4b921b79924643bacd08dcd3d1404ceb6.tar.gz
mpd-46bab7e4b921b79924643bacd08dcd3d1404ceb6.tar.xz
mpd-46bab7e4b921b79924643bacd08dcd3d1404ceb6.zip
Add infrastructure for using multiple event loops
This change adds two configuration options: --with-eventloop=[glib|internal|auto] --with-pollmethod=[epoll|auto] First allows switching between GLib event loop and internal one. Second chooses backend to use for internal event loop. Conditional compilation symbols are changed accordingly. Additional helper macro MPD_OPTIONAL_FUNC_NODEF is added as well.
-rw-r--r--configure.ac68
-rw-r--r--m4/mpd_func.m413
-rw-r--r--src/event/Call.cxx15
-rw-r--r--src/event/DeferredMonitor.cxx16
-rw-r--r--src/event/DeferredMonitor.hxx39
-rw-r--r--src/event/IdleMonitor.cxx17
-rw-r--r--src/event/IdleMonitor.hxx24
-rw-r--r--src/event/Loop.cxx23
-rw-r--r--src/event/Loop.hxx33
-rw-r--r--src/event/MultiSocketMonitor.cxx6
-rw-r--r--src/event/MultiSocketMonitor.hxx48
-rw-r--r--src/event/SocketMonitor.cxx20
-rw-r--r--src/event/SocketMonitor.hxx41
-rw-r--r--src/event/TimeoutMonitor.cxx22
-rw-r--r--src/event/TimeoutMonitor.hxx24
15 files changed, 295 insertions, 114 deletions
diff --git a/configure.ac b/configure.ac
index bfd7ed2ff..f7624a0f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -148,7 +148,6 @@ AC_SEARCH_LIBS([gethostbyname], [nsl])
AC_CHECK_FUNCS(pipe2 accept4)
MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD)
MPD_OPTIONAL_FUNC(signalfd, signalfd, USE_SIGNALFD)
-MPD_OPTIONAL_FUNC(epoll, epoll_create1, USE_EPOLL)
AC_SEARCH_LIBS([exp], [m],,
[AC_MSG_ERROR([exp() not found])])
@@ -157,6 +156,63 @@ AC_CHECK_HEADERS(locale.h)
AC_CHECK_HEADERS(valgrind/memcheck.h)
dnl ---------------------------------------------------------------------------
+dnl Event loop selection
+dnl ---------------------------------------------------------------------------
+
+MPD_OPTIONAL_FUNC_NODEF(epoll, epoll_create1)
+
+AC_ARG_WITH(eventloop,
+ AS_HELP_STRING(
+ [--with-eventloop=@<:@glib|internal|auto@:>@],
+ [specify event loop implementation (default=auto)]),,
+ [with_eventloop=auto])
+
+AC_ARG_WITH(pollmethod,
+ AS_HELP_STRING(
+ [--with-pollmethod=@<:@epoll|auto@:>@],
+ [specify poll method for internal event loop (default=auto)]),,
+ [with_pollmethod=auto])
+
+if test "x$with_eventloop" = xauto; then
+ if test "x$enable_epoll" = xyes; then
+ with_eventloop=internal
+ else
+ with_eventloop=glib
+ fi
+fi
+
+case "$with_eventloop" in
+glib)
+ AC_DEFINE(USE_GLIB_EVENTLOOP, 1,
+ [Define to use GLib event loop])
+ ;;
+internal)
+ AC_DEFINE(USE_INTERNAL_EVENTLOOP, 1,
+ [Define to use internal event loop])
+ ;;
+*)
+ AC_MSG_ERROR([unknown eventloop option: $with_eventloop])
+ ;;
+esac
+
+if test "x$with_eventloop" = xinternal; then
+ if test "x$with_pollmethod" = xauto; then
+ if test "x$enable_epoll" = xyes; then
+ with_pollmethod=epoll
+ else
+ AC_MSG_ERROR([no poll method is available for your platform])
+ fi
+ fi
+ case "$with_pollmethod" in
+ epoll)
+ AC_DEFINE(USE_EPOLL, 1, [Define to poll sockets with epoll])
+ ;;
+ *)
+ AC_MSG_ERROR([unknown pollmethod option: $with_pollmethod])
+ esac
+fi
+
+dnl ---------------------------------------------------------------------------
dnl Allow tools to be specifically built
dnl ---------------------------------------------------------------------------
@@ -1620,6 +1676,16 @@ results(soundcloud,[Soundcloud])
printf '\n\t'
results(mms,[MMS])
+printf '\nEvent loop:\n\t'
+case $with_eventloop in
+glib)
+ printf 'GLib'
+ ;;
+internal)
+ printf 'Internal (%s)' $with_pollmethod
+ ;;
+esac
+
printf '\n\n##########################################\n\n'
echo 'Generating files needed for compilation'
diff --git a/m4/mpd_func.m4 b/m4/mpd_func.m4
index d12d27062..5f2bf8f3d 100644
--- a/m4/mpd_func.m4
+++ b/m4/mpd_func.m4
@@ -10,3 +10,16 @@ AC_DEFUN([MPD_OPTIONAL_FUNC], [
[AC_CHECK_FUNC([$2],
[AC_DEFINE([$3], 1, [Define to use $1])],)])
])
+
+dnl MPD_OPTIONAL_FUNC_NODEF(name, func)
+dnl
+dnl Allow the user to enable or disable the use of a function.
+dnl Works similar to MPD_OPTIONAL_FUNC, however MPD_OPTIONAL_FUNC_NODEF
+dnl does not invoke AC_DEFINE when function is enabled. Shell variable
+dnl enable_$name is set to "yes" instead.
+AC_DEFUN([MPD_OPTIONAL_FUNC_NODEF], [
+ AC_ARG_ENABLE([$1],
+ AS_HELP_STRING([--enable-$1],
+ [use the function "$1" (default: auto)]),,
+ [AC_CHECK_FUNC([$2], [enable_$1=yes],)])
+])
diff --git a/src/event/Call.cxx b/src/event/Call.cxx
index ab1d5ffbd..7767824f9 100644
--- a/src/event/Call.cxx
+++ b/src/event/Call.cxx
@@ -28,7 +28,7 @@
#include <assert.h>
class BlockingCallMonitor final
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
: DeferredMonitor
#endif
{
@@ -40,20 +40,22 @@ class BlockingCallMonitor final
bool done;
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
BlockingCallMonitor(EventLoop &loop, std::function<void()> &&_f)
:f(std::move(_f)), done(false) {
loop.AddCall([this](){
this->DoRun();
});
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
BlockingCallMonitor(EventLoop &_loop, std::function<void()> &&_f)
:DeferredMonitor(_loop), f(std::move(_f)), done(false) {}
#endif
void Run() {
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
assert(!done);
Schedule();
@@ -65,13 +67,14 @@ public:
mutex.unlock();
}
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
private:
virtual void RunDeferred() override {
DoRun();
}
+#endif
-#else
+#ifdef USE_INTERNAL_EVENTLOOP
public:
#endif
void DoRun() {
diff --git a/src/event/DeferredMonitor.cxx b/src/event/DeferredMonitor.cxx
index 4ffffaa89..40b4b0b62 100644
--- a/src/event/DeferredMonitor.cxx
+++ b/src/event/DeferredMonitor.cxx
@@ -24,9 +24,10 @@
void
DeferredMonitor::Cancel()
{
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
pending = false;
-#else
+#endif
+#ifdef USE_GLIB_EVENTLOOP
const auto id = source_id.exchange(0);
if (id != 0)
g_source_remove(id);
@@ -36,10 +37,11 @@ DeferredMonitor::Cancel()
void
DeferredMonitor::Schedule()
{
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
if (!pending.exchange(true))
fd.Write();
-#else
+#endif
+#ifdef USE_GLIB_EVENTLOOP
const unsigned id = loop.AddIdle(Callback, this);
const auto old_id = source_id.exchange(id);
if (old_id != 0)
@@ -47,7 +49,7 @@ DeferredMonitor::Schedule()
#endif
}
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
bool
DeferredMonitor::OnSocketReady(unsigned)
@@ -60,7 +62,9 @@ DeferredMonitor::OnSocketReady(unsigned)
return true;
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
void
DeferredMonitor::Run()
diff --git a/src/event/DeferredMonitor.hxx b/src/event/DeferredMonitor.hxx
index 2380fb66f..d4c812e44 100644
--- a/src/event/DeferredMonitor.hxx
+++ b/src/event/DeferredMonitor.hxx
@@ -23,10 +23,12 @@
#include "check.h"
#include "Compiler.h"
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
#include "SocketMonitor.hxx"
#include "WakeFD.hxx"
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
#include <glib.h>
#endif
@@ -38,44 +40,51 @@ class EventLoop;
* Defer execution of an event into an #EventLoop.
*/
class DeferredMonitor
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
: private SocketMonitor
#endif
{
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
std::atomic_bool pending;
WakeFD fd;
-#else
- EventLoop &loop;
+#endif
+#ifdef USE_GLIB_EVENTLOOP
+ EventLoop &loop;
std::atomic<guint> source_id;
#endif
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
DeferredMonitor(EventLoop &_loop)
:SocketMonitor(_loop), pending(false) {
SocketMonitor::Open(fd.Get());
SocketMonitor::Schedule(SocketMonitor::READ);
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
DeferredMonitor(EventLoop &_loop)
:loop(_loop), source_id(0) {}
#endif
~DeferredMonitor() {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
/* avoid closing the WakeFD twice */
SocketMonitor::Steal();
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
Cancel();
#endif
}
EventLoop &GetEventLoop() {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
return SocketMonitor::GetEventLoop();
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
return loop;
#endif
}
@@ -87,9 +96,11 @@ protected:
virtual void RunDeferred() = 0;
private:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
virtual bool OnSocketReady(unsigned flags) override final;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
void Run();
static gboolean Callback(gpointer data);
#endif
diff --git a/src/event/IdleMonitor.cxx b/src/event/IdleMonitor.cxx
index c99c66b26..8d25407b5 100644
--- a/src/event/IdleMonitor.cxx
+++ b/src/event/IdleMonitor.cxx
@@ -29,10 +29,11 @@ IdleMonitor::Cancel()
if (!IsActive())
return;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
active = false;
loop.RemoveIdle(*this);
-#else
+#endif
+#ifdef USE_GLIB_EVENTLOOP
g_source_remove(source_id);
source_id = 0;
#endif
@@ -47,10 +48,11 @@ IdleMonitor::Schedule()
/* already scheduled */
return;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
active = true;
loop.AddIdle(*this);
-#else
+#endif
+#ifdef USE_GLIB_EVENTLOOP
source_id = loop.AddIdle(Callback, this);
#endif
}
@@ -60,10 +62,11 @@ IdleMonitor::Run()
{
assert(loop.IsInside());
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
assert(active);
active = false;
-#else
+#endif
+#ifdef USE_GLIB_EVENTLOOP
assert(source_id != 0);
source_id = 0;
#endif
@@ -71,7 +74,7 @@ IdleMonitor::Run()
OnIdle();
}
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
gboolean
IdleMonitor::Callback(gpointer data)
diff --git a/src/event/IdleMonitor.hxx b/src/event/IdleMonitor.hxx
index c8e79eb1d..b040915e7 100644
--- a/src/event/IdleMonitor.hxx
+++ b/src/event/IdleMonitor.hxx
@@ -22,7 +22,7 @@
#include "check.h"
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
#include <glib.h>
#endif
@@ -34,23 +34,27 @@ class EventLoop;
* methods must be run from EventLoop's thread.
*/
class IdleMonitor {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
friend class EventLoop;
#endif
EventLoop &loop;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
bool active;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
guint source_id;
#endif
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
IdleMonitor(EventLoop &_loop)
:loop(_loop), active(false) {}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
IdleMonitor(EventLoop &_loop)
:loop(_loop), source_id(0) {}
#endif
@@ -64,9 +68,11 @@ public:
}
bool IsActive() const {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
return active;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
return source_id != 0;
#endif
}
@@ -79,7 +85,7 @@ protected:
private:
void Run();
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
static gboolean Callback(gpointer data);
#endif
};
diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx
index 5aa24aea2..ccba7bb45 100644
--- a/src/event/Loop.cxx
+++ b/src/event/Loop.cxx
@@ -20,7 +20,7 @@
#include "config.h"
#include "Loop.hxx"
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
#include "system/Clock.hxx"
#include "TimeoutMonitor.hxx"
@@ -33,7 +33,9 @@ EventLoop::EventLoop(Default)
:SocketMonitor(*this),
now_ms(::MonotonicClockMS()),
quit(false),
+#ifdef USE_EPOLL
n_events(0),
+#endif
thread(ThreadId::Null())
{
SocketMonitor::Open(wake_fd.Get());
@@ -61,16 +63,20 @@ EventLoop::Break()
void
EventLoop::Abandon(SocketMonitor &m)
{
+#ifdef USE_EPOLL
for (unsigned i = 0, n = n_events; i < n; ++i)
if (events[i].data.ptr == &m)
events[i].events = 0;
+#endif
}
bool
EventLoop::RemoveFD(int _fd, SocketMonitor &m)
{
+#ifdef USE_EPOLL
Abandon(m);
return epoll.Remove(_fd);
+#endif
}
void
@@ -115,7 +121,7 @@ EventLoop::Run()
assert(thread.IsNull());
thread = ThreadId::GetCurrent();
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
assert(!quit);
do {
@@ -162,6 +168,7 @@ EventLoop::Run()
timeout */
continue;
+#ifdef USE_EPOLL
/* wait for new event */
const int n = epoll.Wait(events, MAX_EVENTS, timeout_ms);
@@ -186,15 +193,19 @@ EventLoop::Run()
}
n_events = 0;
+#endif
} while (!quit);
-#else
+
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
g_main_loop_run(loop);
#endif
assert(thread.IsInside());
}
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
void
EventLoop::AddCall(std::function<void()> &&f)
@@ -229,7 +240,9 @@ EventLoop::OnSocketReady(gcc_unused unsigned flags)
return true;
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
guint
EventLoop::AddIdle(GSourceFunc function, gpointer data)
diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx
index 223527853..f188c7cc0 100644
--- a/src/event/Loop.hxx
+++ b/src/event/Loop.hxx
@@ -24,8 +24,11 @@
#include "thread/Id.hxx"
#include "Compiler.h"
+#ifdef USE_INTERNAL_EVENTLOOP
#ifdef USE_EPOLL
#include "system/EPollFD.hxx"
+#endif
+
#include "thread/Mutex.hxx"
#include "WakeFD.hxx"
#include "SocketMonitor.hxx"
@@ -33,11 +36,13 @@
#include <functional>
#include <list>
#include <set>
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
#include <glib.h>
#endif
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
class TimeoutMonitor;
class IdleMonitor;
class SocketMonitor;
@@ -55,11 +60,11 @@ class SocketMonitor;
* @see SocketMonitor, MultiSocketMonitor, TimeoutMonitor, IdleMonitor
*/
class EventLoop final
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
: private SocketMonitor
#endif
{
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
struct TimerRecord {
/**
* Projected monotonic_clock_ms() value when this
@@ -82,8 +87,6 @@ class EventLoop final
}
};
- EPollFD epoll;
-
WakeFD wake_fd;
std::multiset<TimerRecord> timers;
@@ -96,10 +99,16 @@ class EventLoop final
bool quit;
+#ifdef USE_EPOLL
+ EPollFD epoll;
static constexpr unsigned MAX_EVENTS = 16;
unsigned n_events;
epoll_event events[MAX_EVENTS];
-#else
+#endif
+
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
GMainContext *context;
GMainLoop *loop;
#endif
@@ -110,7 +119,7 @@ class EventLoop final
ThreadId thread;
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
struct Default {};
EventLoop(Default dummy=Default());
@@ -131,11 +140,15 @@ public:
void Break();
bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
+#ifdef USE_EPOLL
return epoll.Add(_fd, flags, &m);
+#endif
}
bool ModifyFD(int _fd, unsigned flags, SocketMonitor &m) {
+#ifdef USE_EPOLL
return epoll.Modify(_fd, flags, &m);
+#endif
}
/**
@@ -165,7 +178,9 @@ private:
virtual bool OnSocketReady(unsigned flags) override;
public:
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
EventLoop()
:context(g_main_context_new()),
loop(g_main_loop_new(context, false)),
diff --git a/src/event/MultiSocketMonitor.cxx b/src/event/MultiSocketMonitor.cxx
index bd1aa6fef..f26ab6c28 100644
--- a/src/event/MultiSocketMonitor.cxx
+++ b/src/event/MultiSocketMonitor.cxx
@@ -25,7 +25,7 @@
#include <assert.h>
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
MultiSocketMonitor::MultiSocketMonitor(EventLoop &_loop)
:IdleMonitor(_loop), TimeoutMonitor(_loop), ready(false) {
@@ -65,7 +65,9 @@ MultiSocketMonitor::OnIdle()
}
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
/**
* The vtable for our GSource implementation. Unfortunately, we
diff --git a/src/event/MultiSocketMonitor.hxx b/src/event/MultiSocketMonitor.hxx
index 7ca666246..fed6929c1 100644
--- a/src/event/MultiSocketMonitor.hxx
+++ b/src/event/MultiSocketMonitor.hxx
@@ -23,11 +23,13 @@
#include "check.h"
#include "Compiler.h"
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
#include "IdleMonitor.hxx"
#include "TimeoutMonitor.hxx"
#include "SocketMonitor.hxx"
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
#include <glib.h>
#endif
@@ -53,11 +55,11 @@ class EventLoop;
* DispatchSockets() will be called if at least one socket is ready.
*/
class MultiSocketMonitor
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
: private IdleMonitor, private TimeoutMonitor
#endif
{
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
class SingleFD final : public SocketMonitor {
MultiSocketMonitor &multi;
@@ -102,7 +104,9 @@ class MultiSocketMonitor
friend class SingleFD;
bool ready, refresh;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
struct Source {
GSource base;
@@ -141,12 +145,14 @@ class MultiSocketMonitor
std::forward_list<SingleFD> fds;
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
static constexpr unsigned READ = SocketMonitor::READ;
static constexpr unsigned WRITE = SocketMonitor::WRITE;
static constexpr unsigned ERROR = SocketMonitor::ERROR;
static constexpr unsigned HANGUP = SocketMonitor::HANGUP;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
static constexpr unsigned READ = G_IO_IN;
static constexpr unsigned WRITE = G_IO_OUT;
static constexpr unsigned ERROR = G_IO_ERR;
@@ -156,16 +162,18 @@ public:
MultiSocketMonitor(EventLoop &_loop);
~MultiSocketMonitor();
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
using IdleMonitor::GetEventLoop;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
EventLoop &GetEventLoop() {
return loop;
}
#endif
public:
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
gcc_pure
uint64_t GetTime() const {
return g_source_get_time(&source->base);
@@ -173,10 +181,12 @@ public:
#endif
void InvalidateSockets() {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
refresh = true;
IdleMonitor::Schedule();
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
/* no-op because GLib always calls the GSource's
"prepare" method before each poll() anyway */
#endif
@@ -184,7 +194,7 @@ public:
void AddSocket(int fd, unsigned events) {
fds.emplace_front(*this, fd, events);
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
g_source_add_poll(&source->base, &fds.front().pfd);
#endif
}
@@ -201,9 +211,11 @@ public:
i->SetEvents(events);
prev = i;
} else {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
i->Steal();
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
g_source_remove_poll(&source->base, &i->pfd);
#endif
fds.erase_after(prev);
@@ -218,7 +230,7 @@ protected:
virtual int PrepareSockets() = 0;
virtual void DispatchSockets() = 0;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
private:
void SetReady() {
ready = true;
@@ -234,7 +246,9 @@ private:
virtual void OnIdle() final;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
public:
/* GSource callbacks */
static gboolean Prepare(GSource *source, gint *timeout_r);
diff --git a/src/event/SocketMonitor.cxx b/src/event/SocketMonitor.cxx
index 2b97059f7..fdef0acb6 100644
--- a/src/event/SocketMonitor.cxx
+++ b/src/event/SocketMonitor.cxx
@@ -32,7 +32,7 @@
#include <sys/socket.h>
#endif
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
void
SocketMonitor::Dispatch(unsigned flags)
@@ -43,7 +43,9 @@ SocketMonitor::Dispatch(unsigned flags)
Cancel();
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
/*
* GSource methods
@@ -113,14 +115,14 @@ void
SocketMonitor::Open(int _fd)
{
assert(fd < 0);
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
assert(source == nullptr);
#endif
assert(_fd >= 0);
fd = _fd;
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
poll = {fd, 0, 0};
source = (Source *)g_source_new(&socket_monitor_source_funcs,
@@ -142,7 +144,7 @@ SocketMonitor::Steal()
int result = fd;
fd = -1;
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
g_source_destroy(&source->base);
g_source_unref(&source->base);
source = nullptr;
@@ -156,7 +158,7 @@ SocketMonitor::Abandon()
{
assert(IsDefined());
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
fd = -1;
loop.Abandon(*this);
#else
@@ -178,7 +180,7 @@ SocketMonitor::Schedule(unsigned flags)
if (flags == GetScheduledFlags())
return;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
if (scheduled_flags == 0)
loop.AddFD(fd, flags, *this);
else if (flags == 0)
@@ -187,7 +189,9 @@ SocketMonitor::Schedule(unsigned flags)
loop.ModifyFD(fd, flags, *this);
scheduled_flags = flags;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
poll.events = flags;
poll.revents &= flags;
diff --git a/src/event/SocketMonitor.hxx b/src/event/SocketMonitor.hxx
index ff2864d63..4d3e5aea2 100644
--- a/src/event/SocketMonitor.hxx
+++ b/src/event/SocketMonitor.hxx
@@ -22,9 +22,13 @@
#include "check.h"
+#ifdef USE_INTERNAL_EVENTLOOP
#ifdef USE_EPOLL
#include <sys/epoll.h>
-#else
+#endif
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
#include <glib.h>
#endif
@@ -50,8 +54,7 @@ class EventLoop;
* any of the subscribed events are ready.
*/
class SocketMonitor {
-#ifdef USE_EPOLL
-#else
+#ifdef USE_GLIB_EVENTLOOP
struct Source {
GSource base;
@@ -62,38 +65,46 @@ class SocketMonitor {
int fd;
EventLoop &loop;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
/**
* A bit mask of events that is currently registered in the EventLoop.
*/
unsigned scheduled_flags;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
Source *source;
GPollFD poll;
#endif
public:
+#ifdef USE_INTERNAL_EVENTLOOP
#ifdef USE_EPOLL
static constexpr unsigned READ = EPOLLIN;
static constexpr unsigned WRITE = EPOLLOUT;
static constexpr unsigned ERROR = EPOLLERR;
static constexpr unsigned HANGUP = EPOLLHUP;
-#else
+#endif
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
static constexpr unsigned READ = G_IO_IN;
static constexpr unsigned WRITE = G_IO_OUT;
static constexpr unsigned ERROR = G_IO_ERR;
static constexpr unsigned HANGUP = G_IO_HUP;
-#endif
+#endif
typedef std::make_signed<size_t>::type ssize_t;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
SocketMonitor(EventLoop &_loop)
:fd(-1), loop(_loop), scheduled_flags(0) {}
SocketMonitor(int _fd, EventLoop &_loop)
:fd(_fd), loop(_loop), scheduled_flags(0) {}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
SocketMonitor(EventLoop &_loop)
:fd(-1), loop(_loop), source(nullptr) {}
@@ -134,9 +145,11 @@ public:
unsigned GetScheduledFlags() const {
assert(IsDefined());
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
return scheduled_flags;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
return poll.events;
#endif
}
@@ -173,9 +186,11 @@ protected:
virtual bool OnSocketReady(unsigned flags) = 0;
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
void Dispatch(unsigned flags);
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
/* GSource callbacks */
static gboolean Prepare(GSource *source, gint *timeout_r);
static gboolean Check(GSource *source);
diff --git a/src/event/TimeoutMonitor.cxx b/src/event/TimeoutMonitor.cxx
index cffad6b92..3d7d46324 100644
--- a/src/event/TimeoutMonitor.cxx
+++ b/src/event/TimeoutMonitor.cxx
@@ -25,10 +25,12 @@ void
TimeoutMonitor::Cancel()
{
if (IsActive()) {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
active = false;
loop.CancelTimer(*this);
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
g_source_destroy(source);
g_source_unref(source);
source = nullptr;
@@ -41,10 +43,12 @@ TimeoutMonitor::Schedule(unsigned ms)
{
Cancel();
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
active = true;
loop.AddTimer(*this, ms);
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
source = loop.AddTimeout(ms, Callback, this);
#endif
}
@@ -54,9 +58,11 @@ TimeoutMonitor::ScheduleSeconds(unsigned s)
{
Cancel();
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
Schedule(s * 1000u);
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
source = loop.AddTimeoutSeconds(s, Callback, this);
#endif
}
@@ -64,14 +70,14 @@ TimeoutMonitor::ScheduleSeconds(unsigned s)
void
TimeoutMonitor::Run()
{
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
Cancel();
#endif
OnTimeout();
}
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
gboolean
TimeoutMonitor::Callback(gpointer data)
diff --git a/src/event/TimeoutMonitor.hxx b/src/event/TimeoutMonitor.hxx
index aa2bbea39..568aa27ef 100644
--- a/src/event/TimeoutMonitor.hxx
+++ b/src/event/TimeoutMonitor.hxx
@@ -22,7 +22,7 @@
#include "check.h"
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
#include <glib.h>
#endif
@@ -33,24 +33,28 @@ class EventLoop;
* or Cancel() to cancel it.
*/
class TimeoutMonitor {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
friend class EventLoop;
#endif
EventLoop &loop;
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
bool active;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
GSource *source;
#endif
public:
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
TimeoutMonitor(EventLoop &_loop)
:loop(_loop), active(false) {
}
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
TimeoutMonitor(EventLoop &_loop)
:loop(_loop), source(nullptr) {}
#endif
@@ -64,9 +68,11 @@ public:
}
bool IsActive() const {
-#ifdef USE_EPOLL
+#ifdef USE_INTERNAL_EVENTLOOP
return active;
-#else
+#endif
+
+#ifdef USE_GLIB_EVENTLOOP
return source != nullptr;
#endif
}
@@ -81,7 +87,7 @@ protected:
private:
void Run();
-#ifndef USE_EPOLL
+#ifdef USE_GLIB_EVENTLOOP
static gboolean Callback(gpointer data);
#endif
};