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.
This commit is contained in:
parent
22fb49fa90
commit
46bab7e4b9
68
configure.ac
68
configure.ac
|
@ -148,7 +148,6 @@ AC_SEARCH_LIBS([gethostbyname], [nsl])
|
||||||
AC_CHECK_FUNCS(pipe2 accept4)
|
AC_CHECK_FUNCS(pipe2 accept4)
|
||||||
MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD)
|
MPD_OPTIONAL_FUNC(eventfd, eventfd, USE_EVENTFD)
|
||||||
MPD_OPTIONAL_FUNC(signalfd, signalfd, USE_SIGNALFD)
|
MPD_OPTIONAL_FUNC(signalfd, signalfd, USE_SIGNALFD)
|
||||||
MPD_OPTIONAL_FUNC(epoll, epoll_create1, USE_EPOLL)
|
|
||||||
|
|
||||||
AC_SEARCH_LIBS([exp], [m],,
|
AC_SEARCH_LIBS([exp], [m],,
|
||||||
[AC_MSG_ERROR([exp() not found])])
|
[AC_MSG_ERROR([exp() not found])])
|
||||||
|
@ -156,6 +155,63 @@ AC_SEARCH_LIBS([exp], [m],,
|
||||||
AC_CHECK_HEADERS(locale.h)
|
AC_CHECK_HEADERS(locale.h)
|
||||||
AC_CHECK_HEADERS(valgrind/memcheck.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 ---------------------------------------------------------------------------
|
||||||
dnl Allow tools to be specifically built
|
dnl Allow tools to be specifically built
|
||||||
dnl ---------------------------------------------------------------------------
|
dnl ---------------------------------------------------------------------------
|
||||||
|
@ -1620,6 +1676,16 @@ results(soundcloud,[Soundcloud])
|
||||||
printf '\n\t'
|
printf '\n\t'
|
||||||
results(mms,[MMS])
|
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'
|
printf '\n\n##########################################\n\n'
|
||||||
|
|
||||||
echo 'Generating files needed for compilation'
|
echo 'Generating files needed for compilation'
|
||||||
|
|
|
@ -10,3 +10,16 @@ AC_DEFUN([MPD_OPTIONAL_FUNC], [
|
||||||
[AC_CHECK_FUNC([$2],
|
[AC_CHECK_FUNC([$2],
|
||||||
[AC_DEFINE([$3], 1, [Define to use $1])],)])
|
[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],)])
|
||||||
|
])
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
class BlockingCallMonitor final
|
class BlockingCallMonitor final
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
: DeferredMonitor
|
: DeferredMonitor
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
@ -40,20 +40,22 @@ class BlockingCallMonitor final
|
||||||
bool done;
|
bool done;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
BlockingCallMonitor(EventLoop &loop, std::function<void()> &&_f)
|
BlockingCallMonitor(EventLoop &loop, std::function<void()> &&_f)
|
||||||
:f(std::move(_f)), done(false) {
|
:f(std::move(_f)), done(false) {
|
||||||
loop.AddCall([this](){
|
loop.AddCall([this](){
|
||||||
this->DoRun();
|
this->DoRun();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
BlockingCallMonitor(EventLoop &_loop, std::function<void()> &&_f)
|
BlockingCallMonitor(EventLoop &_loop, std::function<void()> &&_f)
|
||||||
:DeferredMonitor(_loop), f(std::move(_f)), done(false) {}
|
:DeferredMonitor(_loop), f(std::move(_f)), done(false) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Run() {
|
void Run() {
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
assert(!done);
|
assert(!done);
|
||||||
|
|
||||||
Schedule();
|
Schedule();
|
||||||
|
@ -65,13 +67,14 @@ public:
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
private:
|
private:
|
||||||
virtual void RunDeferred() override {
|
virtual void RunDeferred() override {
|
||||||
DoRun();
|
DoRun();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#else
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
public:
|
public:
|
||||||
#endif
|
#endif
|
||||||
void DoRun() {
|
void DoRun() {
|
||||||
|
|
|
@ -24,9 +24,10 @@
|
||||||
void
|
void
|
||||||
DeferredMonitor::Cancel()
|
DeferredMonitor::Cancel()
|
||||||
{
|
{
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
pending = false;
|
pending = false;
|
||||||
#else
|
#endif
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
const auto id = source_id.exchange(0);
|
const auto id = source_id.exchange(0);
|
||||||
if (id != 0)
|
if (id != 0)
|
||||||
g_source_remove(id);
|
g_source_remove(id);
|
||||||
|
@ -36,10 +37,11 @@ DeferredMonitor::Cancel()
|
||||||
void
|
void
|
||||||
DeferredMonitor::Schedule()
|
DeferredMonitor::Schedule()
|
||||||
{
|
{
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
if (!pending.exchange(true))
|
if (!pending.exchange(true))
|
||||||
fd.Write();
|
fd.Write();
|
||||||
#else
|
#endif
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
const unsigned id = loop.AddIdle(Callback, this);
|
const unsigned id = loop.AddIdle(Callback, this);
|
||||||
const auto old_id = source_id.exchange(id);
|
const auto old_id = source_id.exchange(id);
|
||||||
if (old_id != 0)
|
if (old_id != 0)
|
||||||
|
@ -47,7 +49,7 @@ DeferredMonitor::Schedule()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
|
|
||||||
bool
|
bool
|
||||||
DeferredMonitor::OnSocketReady(unsigned)
|
DeferredMonitor::OnSocketReady(unsigned)
|
||||||
|
@ -60,7 +62,9 @@ DeferredMonitor::OnSocketReady(unsigned)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
|
|
||||||
void
|
void
|
||||||
DeferredMonitor::Run()
|
DeferredMonitor::Run()
|
||||||
|
|
|
@ -23,10 +23,12 @@
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
#include "SocketMonitor.hxx"
|
#include "SocketMonitor.hxx"
|
||||||
#include "WakeFD.hxx"
|
#include "WakeFD.hxx"
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -38,44 +40,51 @@ class EventLoop;
|
||||||
* Defer execution of an event into an #EventLoop.
|
* Defer execution of an event into an #EventLoop.
|
||||||
*/
|
*/
|
||||||
class DeferredMonitor
|
class DeferredMonitor
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
: private SocketMonitor
|
: private SocketMonitor
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
std::atomic_bool pending;
|
std::atomic_bool pending;
|
||||||
WakeFD fd;
|
WakeFD fd;
|
||||||
#else
|
#endif
|
||||||
EventLoop &loop;
|
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
|
EventLoop &loop;
|
||||||
std::atomic<guint> source_id;
|
std::atomic<guint> source_id;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
DeferredMonitor(EventLoop &_loop)
|
DeferredMonitor(EventLoop &_loop)
|
||||||
:SocketMonitor(_loop), pending(false) {
|
:SocketMonitor(_loop), pending(false) {
|
||||||
SocketMonitor::Open(fd.Get());
|
SocketMonitor::Open(fd.Get());
|
||||||
SocketMonitor::Schedule(SocketMonitor::READ);
|
SocketMonitor::Schedule(SocketMonitor::READ);
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
DeferredMonitor(EventLoop &_loop)
|
DeferredMonitor(EventLoop &_loop)
|
||||||
:loop(_loop), source_id(0) {}
|
:loop(_loop), source_id(0) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
~DeferredMonitor() {
|
~DeferredMonitor() {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
/* avoid closing the WakeFD twice */
|
/* avoid closing the WakeFD twice */
|
||||||
SocketMonitor::Steal();
|
SocketMonitor::Steal();
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
Cancel();
|
Cancel();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
EventLoop &GetEventLoop() {
|
EventLoop &GetEventLoop() {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
return SocketMonitor::GetEventLoop();
|
return SocketMonitor::GetEventLoop();
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
return loop;
|
return loop;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -87,9 +96,11 @@ protected:
|
||||||
virtual void RunDeferred() = 0;
|
virtual void RunDeferred() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
virtual bool OnSocketReady(unsigned flags) override final;
|
virtual bool OnSocketReady(unsigned flags) override final;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
void Run();
|
void Run();
|
||||||
static gboolean Callback(gpointer data);
|
static gboolean Callback(gpointer data);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,10 +29,11 @@ IdleMonitor::Cancel()
|
||||||
if (!IsActive())
|
if (!IsActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
active = false;
|
active = false;
|
||||||
loop.RemoveIdle(*this);
|
loop.RemoveIdle(*this);
|
||||||
#else
|
#endif
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
g_source_remove(source_id);
|
g_source_remove(source_id);
|
||||||
source_id = 0;
|
source_id = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -47,10 +48,11 @@ IdleMonitor::Schedule()
|
||||||
/* already scheduled */
|
/* already scheduled */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
active = true;
|
active = true;
|
||||||
loop.AddIdle(*this);
|
loop.AddIdle(*this);
|
||||||
#else
|
#endif
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
source_id = loop.AddIdle(Callback, this);
|
source_id = loop.AddIdle(Callback, this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -60,10 +62,11 @@ IdleMonitor::Run()
|
||||||
{
|
{
|
||||||
assert(loop.IsInside());
|
assert(loop.IsInside());
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
assert(active);
|
assert(active);
|
||||||
active = false;
|
active = false;
|
||||||
#else
|
#endif
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
assert(source_id != 0);
|
assert(source_id != 0);
|
||||||
source_id = 0;
|
source_id = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -71,7 +74,7 @@ IdleMonitor::Run()
|
||||||
OnIdle();
|
OnIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
IdleMonitor::Callback(gpointer data)
|
IdleMonitor::Callback(gpointer data)
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -34,23 +34,27 @@ class EventLoop;
|
||||||
* methods must be run from EventLoop's thread.
|
* methods must be run from EventLoop's thread.
|
||||||
*/
|
*/
|
||||||
class IdleMonitor {
|
class IdleMonitor {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
friend class EventLoop;
|
friend class EventLoop;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EventLoop &loop;
|
EventLoop &loop;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
bool active;
|
bool active;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
guint source_id;
|
guint source_id;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
IdleMonitor(EventLoop &_loop)
|
IdleMonitor(EventLoop &_loop)
|
||||||
:loop(_loop), active(false) {}
|
:loop(_loop), active(false) {}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
IdleMonitor(EventLoop &_loop)
|
IdleMonitor(EventLoop &_loop)
|
||||||
:loop(_loop), source_id(0) {}
|
:loop(_loop), source_id(0) {}
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,9 +68,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsActive() const {
|
bool IsActive() const {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
return active;
|
return active;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
return source_id != 0;
|
return source_id != 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -79,7 +85,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Run();
|
void Run();
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
static gboolean Callback(gpointer data);
|
static gboolean Callback(gpointer data);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Loop.hxx"
|
#include "Loop.hxx"
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
|
|
||||||
#include "system/Clock.hxx"
|
#include "system/Clock.hxx"
|
||||||
#include "TimeoutMonitor.hxx"
|
#include "TimeoutMonitor.hxx"
|
||||||
|
@ -33,7 +33,9 @@ EventLoop::EventLoop(Default)
|
||||||
:SocketMonitor(*this),
|
:SocketMonitor(*this),
|
||||||
now_ms(::MonotonicClockMS()),
|
now_ms(::MonotonicClockMS()),
|
||||||
quit(false),
|
quit(false),
|
||||||
|
#ifdef USE_EPOLL
|
||||||
n_events(0),
|
n_events(0),
|
||||||
|
#endif
|
||||||
thread(ThreadId::Null())
|
thread(ThreadId::Null())
|
||||||
{
|
{
|
||||||
SocketMonitor::Open(wake_fd.Get());
|
SocketMonitor::Open(wake_fd.Get());
|
||||||
|
@ -61,16 +63,20 @@ EventLoop::Break()
|
||||||
void
|
void
|
||||||
EventLoop::Abandon(SocketMonitor &m)
|
EventLoop::Abandon(SocketMonitor &m)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_EPOLL
|
||||||
for (unsigned i = 0, n = n_events; i < n; ++i)
|
for (unsigned i = 0, n = n_events; i < n; ++i)
|
||||||
if (events[i].data.ptr == &m)
|
if (events[i].data.ptr == &m)
|
||||||
events[i].events = 0;
|
events[i].events = 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
EventLoop::RemoveFD(int _fd, SocketMonitor &m)
|
EventLoop::RemoveFD(int _fd, SocketMonitor &m)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_EPOLL
|
||||||
Abandon(m);
|
Abandon(m);
|
||||||
return epoll.Remove(_fd);
|
return epoll.Remove(_fd);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -115,7 +121,7 @@ EventLoop::Run()
|
||||||
assert(thread.IsNull());
|
assert(thread.IsNull());
|
||||||
thread = ThreadId::GetCurrent();
|
thread = ThreadId::GetCurrent();
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
assert(!quit);
|
assert(!quit);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -162,6 +168,7 @@ EventLoop::Run()
|
||||||
timeout */
|
timeout */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
#ifdef USE_EPOLL
|
||||||
/* wait for new event */
|
/* wait for new event */
|
||||||
|
|
||||||
const int n = epoll.Wait(events, MAX_EVENTS, timeout_ms);
|
const int n = epoll.Wait(events, MAX_EVENTS, timeout_ms);
|
||||||
|
@ -186,15 +193,19 @@ EventLoop::Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
n_events = 0;
|
n_events = 0;
|
||||||
|
#endif
|
||||||
} while (!quit);
|
} while (!quit);
|
||||||
#else
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
g_main_loop_run(loop);
|
g_main_loop_run(loop);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(thread.IsInside());
|
assert(thread.IsInside());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
|
|
||||||
void
|
void
|
||||||
EventLoop::AddCall(std::function<void()> &&f)
|
EventLoop::AddCall(std::function<void()> &&f)
|
||||||
|
@ -229,7 +240,9 @@ EventLoop::OnSocketReady(gcc_unused unsigned flags)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
|
|
||||||
guint
|
guint
|
||||||
EventLoop::AddIdle(GSourceFunc function, gpointer data)
|
EventLoop::AddIdle(GSourceFunc function, gpointer data)
|
||||||
|
|
|
@ -24,8 +24,11 @@
|
||||||
#include "thread/Id.hxx"
|
#include "thread/Id.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_EPOLL
|
||||||
#include "system/EPollFD.hxx"
|
#include "system/EPollFD.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
#include "WakeFD.hxx"
|
#include "WakeFD.hxx"
|
||||||
#include "SocketMonitor.hxx"
|
#include "SocketMonitor.hxx"
|
||||||
|
@ -33,11 +36,13 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <set>
|
#include <set>
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
class TimeoutMonitor;
|
class TimeoutMonitor;
|
||||||
class IdleMonitor;
|
class IdleMonitor;
|
||||||
class SocketMonitor;
|
class SocketMonitor;
|
||||||
|
@ -55,11 +60,11 @@ class SocketMonitor;
|
||||||
* @see SocketMonitor, MultiSocketMonitor, TimeoutMonitor, IdleMonitor
|
* @see SocketMonitor, MultiSocketMonitor, TimeoutMonitor, IdleMonitor
|
||||||
*/
|
*/
|
||||||
class EventLoop final
|
class EventLoop final
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
: private SocketMonitor
|
: private SocketMonitor
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
struct TimerRecord {
|
struct TimerRecord {
|
||||||
/**
|
/**
|
||||||
* Projected monotonic_clock_ms() value when this
|
* Projected monotonic_clock_ms() value when this
|
||||||
|
@ -82,8 +87,6 @@ class EventLoop final
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
EPollFD epoll;
|
|
||||||
|
|
||||||
WakeFD wake_fd;
|
WakeFD wake_fd;
|
||||||
|
|
||||||
std::multiset<TimerRecord> timers;
|
std::multiset<TimerRecord> timers;
|
||||||
|
@ -96,10 +99,16 @@ class EventLoop final
|
||||||
|
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
||||||
|
#ifdef USE_EPOLL
|
||||||
|
EPollFD epoll;
|
||||||
static constexpr unsigned MAX_EVENTS = 16;
|
static constexpr unsigned MAX_EVENTS = 16;
|
||||||
unsigned n_events;
|
unsigned n_events;
|
||||||
epoll_event events[MAX_EVENTS];
|
epoll_event events[MAX_EVENTS];
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
GMainContext *context;
|
GMainContext *context;
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
#endif
|
#endif
|
||||||
|
@ -110,7 +119,7 @@ class EventLoop final
|
||||||
ThreadId thread;
|
ThreadId thread;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
struct Default {};
|
struct Default {};
|
||||||
|
|
||||||
EventLoop(Default dummy=Default());
|
EventLoop(Default dummy=Default());
|
||||||
|
@ -131,11 +140,15 @@ public:
|
||||||
void Break();
|
void Break();
|
||||||
|
|
||||||
bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
|
bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
|
||||||
|
#ifdef USE_EPOLL
|
||||||
return epoll.Add(_fd, flags, &m);
|
return epoll.Add(_fd, flags, &m);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModifyFD(int _fd, unsigned flags, SocketMonitor &m) {
|
bool ModifyFD(int _fd, unsigned flags, SocketMonitor &m) {
|
||||||
|
#ifdef USE_EPOLL
|
||||||
return epoll.Modify(_fd, flags, &m);
|
return epoll.Modify(_fd, flags, &m);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,7 +178,9 @@ private:
|
||||||
virtual bool OnSocketReady(unsigned flags) override;
|
virtual bool OnSocketReady(unsigned flags) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
EventLoop()
|
EventLoop()
|
||||||
:context(g_main_context_new()),
|
:context(g_main_context_new()),
|
||||||
loop(g_main_loop_new(context, false)),
|
loop(g_main_loop_new(context, false)),
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
|
|
||||||
MultiSocketMonitor::MultiSocketMonitor(EventLoop &_loop)
|
MultiSocketMonitor::MultiSocketMonitor(EventLoop &_loop)
|
||||||
:IdleMonitor(_loop), TimeoutMonitor(_loop), ready(false) {
|
: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
|
* The vtable for our GSource implementation. Unfortunately, we
|
||||||
|
|
|
@ -23,11 +23,13 @@
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
#include "IdleMonitor.hxx"
|
#include "IdleMonitor.hxx"
|
||||||
#include "TimeoutMonitor.hxx"
|
#include "TimeoutMonitor.hxx"
|
||||||
#include "SocketMonitor.hxx"
|
#include "SocketMonitor.hxx"
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -53,11 +55,11 @@ class EventLoop;
|
||||||
* DispatchSockets() will be called if at least one socket is ready.
|
* DispatchSockets() will be called if at least one socket is ready.
|
||||||
*/
|
*/
|
||||||
class MultiSocketMonitor
|
class MultiSocketMonitor
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
: private IdleMonitor, private TimeoutMonitor
|
: private IdleMonitor, private TimeoutMonitor
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
class SingleFD final : public SocketMonitor {
|
class SingleFD final : public SocketMonitor {
|
||||||
MultiSocketMonitor &multi;
|
MultiSocketMonitor &multi;
|
||||||
|
|
||||||
|
@ -102,7 +104,9 @@ class MultiSocketMonitor
|
||||||
friend class SingleFD;
|
friend class SingleFD;
|
||||||
|
|
||||||
bool ready, refresh;
|
bool ready, refresh;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
struct Source {
|
struct Source {
|
||||||
GSource base;
|
GSource base;
|
||||||
|
|
||||||
|
@ -141,12 +145,14 @@ class MultiSocketMonitor
|
||||||
std::forward_list<SingleFD> fds;
|
std::forward_list<SingleFD> fds;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
static constexpr unsigned READ = SocketMonitor::READ;
|
static constexpr unsigned READ = SocketMonitor::READ;
|
||||||
static constexpr unsigned WRITE = SocketMonitor::WRITE;
|
static constexpr unsigned WRITE = SocketMonitor::WRITE;
|
||||||
static constexpr unsigned ERROR = SocketMonitor::ERROR;
|
static constexpr unsigned ERROR = SocketMonitor::ERROR;
|
||||||
static constexpr unsigned HANGUP = SocketMonitor::HANGUP;
|
static constexpr unsigned HANGUP = SocketMonitor::HANGUP;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
static constexpr unsigned READ = G_IO_IN;
|
static constexpr unsigned READ = G_IO_IN;
|
||||||
static constexpr unsigned WRITE = G_IO_OUT;
|
static constexpr unsigned WRITE = G_IO_OUT;
|
||||||
static constexpr unsigned ERROR = G_IO_ERR;
|
static constexpr unsigned ERROR = G_IO_ERR;
|
||||||
|
@ -156,16 +162,18 @@ public:
|
||||||
MultiSocketMonitor(EventLoop &_loop);
|
MultiSocketMonitor(EventLoop &_loop);
|
||||||
~MultiSocketMonitor();
|
~MultiSocketMonitor();
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
using IdleMonitor::GetEventLoop;
|
using IdleMonitor::GetEventLoop;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
EventLoop &GetEventLoop() {
|
EventLoop &GetEventLoop() {
|
||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
gcc_pure
|
gcc_pure
|
||||||
uint64_t GetTime() const {
|
uint64_t GetTime() const {
|
||||||
return g_source_get_time(&source->base);
|
return g_source_get_time(&source->base);
|
||||||
|
@ -173,10 +181,12 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void InvalidateSockets() {
|
void InvalidateSockets() {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
refresh = true;
|
refresh = true;
|
||||||
IdleMonitor::Schedule();
|
IdleMonitor::Schedule();
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
/* no-op because GLib always calls the GSource's
|
/* no-op because GLib always calls the GSource's
|
||||||
"prepare" method before each poll() anyway */
|
"prepare" method before each poll() anyway */
|
||||||
#endif
|
#endif
|
||||||
|
@ -184,7 +194,7 @@ public:
|
||||||
|
|
||||||
void AddSocket(int fd, unsigned events) {
|
void AddSocket(int fd, unsigned events) {
|
||||||
fds.emplace_front(*this, fd, events);
|
fds.emplace_front(*this, fd, events);
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
g_source_add_poll(&source->base, &fds.front().pfd);
|
g_source_add_poll(&source->base, &fds.front().pfd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -201,9 +211,11 @@ public:
|
||||||
i->SetEvents(events);
|
i->SetEvents(events);
|
||||||
prev = i;
|
prev = i;
|
||||||
} else {
|
} else {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
i->Steal();
|
i->Steal();
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
g_source_remove_poll(&source->base, &i->pfd);
|
g_source_remove_poll(&source->base, &i->pfd);
|
||||||
#endif
|
#endif
|
||||||
fds.erase_after(prev);
|
fds.erase_after(prev);
|
||||||
|
@ -218,7 +230,7 @@ protected:
|
||||||
virtual int PrepareSockets() = 0;
|
virtual int PrepareSockets() = 0;
|
||||||
virtual void DispatchSockets() = 0;
|
virtual void DispatchSockets() = 0;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
private:
|
private:
|
||||||
void SetReady() {
|
void SetReady() {
|
||||||
ready = true;
|
ready = true;
|
||||||
|
@ -234,7 +246,9 @@ private:
|
||||||
|
|
||||||
virtual void OnIdle() final;
|
virtual void OnIdle() final;
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
public:
|
public:
|
||||||
/* GSource callbacks */
|
/* GSource callbacks */
|
||||||
static gboolean Prepare(GSource *source, gint *timeout_r);
|
static gboolean Prepare(GSource *source, gint *timeout_r);
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
|
|
||||||
void
|
void
|
||||||
SocketMonitor::Dispatch(unsigned flags)
|
SocketMonitor::Dispatch(unsigned flags)
|
||||||
|
@ -43,7 +43,9 @@ SocketMonitor::Dispatch(unsigned flags)
|
||||||
Cancel();
|
Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GSource methods
|
* GSource methods
|
||||||
|
@ -113,14 +115,14 @@ void
|
||||||
SocketMonitor::Open(int _fd)
|
SocketMonitor::Open(int _fd)
|
||||||
{
|
{
|
||||||
assert(fd < 0);
|
assert(fd < 0);
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
assert(source == nullptr);
|
assert(source == nullptr);
|
||||||
#endif
|
#endif
|
||||||
assert(_fd >= 0);
|
assert(_fd >= 0);
|
||||||
|
|
||||||
fd = _fd;
|
fd = _fd;
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
poll = {fd, 0, 0};
|
poll = {fd, 0, 0};
|
||||||
|
|
||||||
source = (Source *)g_source_new(&socket_monitor_source_funcs,
|
source = (Source *)g_source_new(&socket_monitor_source_funcs,
|
||||||
|
@ -142,7 +144,7 @@ SocketMonitor::Steal()
|
||||||
int result = fd;
|
int result = fd;
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
g_source_destroy(&source->base);
|
g_source_destroy(&source->base);
|
||||||
g_source_unref(&source->base);
|
g_source_unref(&source->base);
|
||||||
source = nullptr;
|
source = nullptr;
|
||||||
|
@ -156,7 +158,7 @@ SocketMonitor::Abandon()
|
||||||
{
|
{
|
||||||
assert(IsDefined());
|
assert(IsDefined());
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
fd = -1;
|
fd = -1;
|
||||||
loop.Abandon(*this);
|
loop.Abandon(*this);
|
||||||
#else
|
#else
|
||||||
|
@ -178,7 +180,7 @@ SocketMonitor::Schedule(unsigned flags)
|
||||||
if (flags == GetScheduledFlags())
|
if (flags == GetScheduledFlags())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
if (scheduled_flags == 0)
|
if (scheduled_flags == 0)
|
||||||
loop.AddFD(fd, flags, *this);
|
loop.AddFD(fd, flags, *this);
|
||||||
else if (flags == 0)
|
else if (flags == 0)
|
||||||
|
@ -187,7 +189,9 @@ SocketMonitor::Schedule(unsigned flags)
|
||||||
loop.ModifyFD(fd, flags, *this);
|
loop.ModifyFD(fd, flags, *this);
|
||||||
|
|
||||||
scheduled_flags = flags;
|
scheduled_flags = flags;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
poll.events = flags;
|
poll.events = flags;
|
||||||
poll.revents &= flags;
|
poll.revents &= flags;
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,13 @@
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_EPOLL
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#else
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -50,8 +54,7 @@ class EventLoop;
|
||||||
* any of the subscribed events are ready.
|
* any of the subscribed events are ready.
|
||||||
*/
|
*/
|
||||||
class SocketMonitor {
|
class SocketMonitor {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#else
|
|
||||||
struct Source {
|
struct Source {
|
||||||
GSource base;
|
GSource base;
|
||||||
|
|
||||||
|
@ -62,38 +65,46 @@ class SocketMonitor {
|
||||||
int fd;
|
int fd;
|
||||||
EventLoop &loop;
|
EventLoop &loop;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
/**
|
/**
|
||||||
* A bit mask of events that is currently registered in the EventLoop.
|
* A bit mask of events that is currently registered in the EventLoop.
|
||||||
*/
|
*/
|
||||||
unsigned scheduled_flags;
|
unsigned scheduled_flags;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
Source *source;
|
Source *source;
|
||||||
GPollFD poll;
|
GPollFD poll;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_EPOLL
|
||||||
static constexpr unsigned READ = EPOLLIN;
|
static constexpr unsigned READ = EPOLLIN;
|
||||||
static constexpr unsigned WRITE = EPOLLOUT;
|
static constexpr unsigned WRITE = EPOLLOUT;
|
||||||
static constexpr unsigned ERROR = EPOLLERR;
|
static constexpr unsigned ERROR = EPOLLERR;
|
||||||
static constexpr unsigned HANGUP = EPOLLHUP;
|
static constexpr unsigned HANGUP = EPOLLHUP;
|
||||||
#else
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
static constexpr unsigned READ = G_IO_IN;
|
static constexpr unsigned READ = G_IO_IN;
|
||||||
static constexpr unsigned WRITE = G_IO_OUT;
|
static constexpr unsigned WRITE = G_IO_OUT;
|
||||||
static constexpr unsigned ERROR = G_IO_ERR;
|
static constexpr unsigned ERROR = G_IO_ERR;
|
||||||
static constexpr unsigned HANGUP = G_IO_HUP;
|
static constexpr unsigned HANGUP = G_IO_HUP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef std::make_signed<size_t>::type ssize_t;
|
typedef std::make_signed<size_t>::type ssize_t;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
SocketMonitor(EventLoop &_loop)
|
SocketMonitor(EventLoop &_loop)
|
||||||
:fd(-1), loop(_loop), scheduled_flags(0) {}
|
:fd(-1), loop(_loop), scheduled_flags(0) {}
|
||||||
|
|
||||||
SocketMonitor(int _fd, EventLoop &_loop)
|
SocketMonitor(int _fd, EventLoop &_loop)
|
||||||
:fd(_fd), loop(_loop), scheduled_flags(0) {}
|
:fd(_fd), loop(_loop), scheduled_flags(0) {}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
SocketMonitor(EventLoop &_loop)
|
SocketMonitor(EventLoop &_loop)
|
||||||
:fd(-1), loop(_loop), source(nullptr) {}
|
:fd(-1), loop(_loop), source(nullptr) {}
|
||||||
|
|
||||||
|
@ -134,9 +145,11 @@ public:
|
||||||
unsigned GetScheduledFlags() const {
|
unsigned GetScheduledFlags() const {
|
||||||
assert(IsDefined());
|
assert(IsDefined());
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
return scheduled_flags;
|
return scheduled_flags;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
return poll.events;
|
return poll.events;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -173,9 +186,11 @@ protected:
|
||||||
virtual bool OnSocketReady(unsigned flags) = 0;
|
virtual bool OnSocketReady(unsigned flags) = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
void Dispatch(unsigned flags);
|
void Dispatch(unsigned flags);
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
/* GSource callbacks */
|
/* GSource callbacks */
|
||||||
static gboolean Prepare(GSource *source, gint *timeout_r);
|
static gboolean Prepare(GSource *source, gint *timeout_r);
|
||||||
static gboolean Check(GSource *source);
|
static gboolean Check(GSource *source);
|
||||||
|
|
|
@ -25,10 +25,12 @@ void
|
||||||
TimeoutMonitor::Cancel()
|
TimeoutMonitor::Cancel()
|
||||||
{
|
{
|
||||||
if (IsActive()) {
|
if (IsActive()) {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
active = false;
|
active = false;
|
||||||
loop.CancelTimer(*this);
|
loop.CancelTimer(*this);
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
g_source_destroy(source);
|
g_source_destroy(source);
|
||||||
g_source_unref(source);
|
g_source_unref(source);
|
||||||
source = nullptr;
|
source = nullptr;
|
||||||
|
@ -41,10 +43,12 @@ TimeoutMonitor::Schedule(unsigned ms)
|
||||||
{
|
{
|
||||||
Cancel();
|
Cancel();
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
active = true;
|
active = true;
|
||||||
loop.AddTimer(*this, ms);
|
loop.AddTimer(*this, ms);
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
source = loop.AddTimeout(ms, Callback, this);
|
source = loop.AddTimeout(ms, Callback, this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -54,9 +58,11 @@ TimeoutMonitor::ScheduleSeconds(unsigned s)
|
||||||
{
|
{
|
||||||
Cancel();
|
Cancel();
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
Schedule(s * 1000u);
|
Schedule(s * 1000u);
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
source = loop.AddTimeoutSeconds(s, Callback, this);
|
source = loop.AddTimeoutSeconds(s, Callback, this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -64,14 +70,14 @@ TimeoutMonitor::ScheduleSeconds(unsigned s)
|
||||||
void
|
void
|
||||||
TimeoutMonitor::Run()
|
TimeoutMonitor::Run()
|
||||||
{
|
{
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
Cancel();
|
Cancel();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
OnTimeout();
|
OnTimeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
TimeoutMonitor::Callback(gpointer data)
|
TimeoutMonitor::Callback(gpointer data)
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -33,24 +33,28 @@ class EventLoop;
|
||||||
* or Cancel() to cancel it.
|
* or Cancel() to cancel it.
|
||||||
*/
|
*/
|
||||||
class TimeoutMonitor {
|
class TimeoutMonitor {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
friend class EventLoop;
|
friend class EventLoop;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EventLoop &loop;
|
EventLoop &loop;
|
||||||
|
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
bool active;
|
bool active;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
GSource *source;
|
GSource *source;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
TimeoutMonitor(EventLoop &_loop)
|
TimeoutMonitor(EventLoop &_loop)
|
||||||
:loop(_loop), active(false) {
|
:loop(_loop), active(false) {
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
TimeoutMonitor(EventLoop &_loop)
|
TimeoutMonitor(EventLoop &_loop)
|
||||||
:loop(_loop), source(nullptr) {}
|
:loop(_loop), source(nullptr) {}
|
||||||
#endif
|
#endif
|
||||||
|
@ -64,9 +68,11 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsActive() const {
|
bool IsActive() const {
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_INTERNAL_EVENTLOOP
|
||||||
return active;
|
return active;
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
return source != nullptr;
|
return source != nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -81,7 +87,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
#ifndef USE_EPOLL
|
#ifdef USE_GLIB_EVENTLOOP
|
||||||
static gboolean Callback(gpointer data);
|
static gboolean Callback(gpointer data);
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue