aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--src/event/Loop.cxx41
-rw-r--r--src/event/Loop.hxx24
-rw-r--r--src/event/PollGroup.hxx29
-rw-r--r--src/event/PollGroupEPoll.hxx91
-rw-r--r--src/event/SocketMonitor.cxx3
-rw-r--r--src/event/SocketMonitor.hxx14
7 files changed, 149 insertions, 55 deletions
diff --git a/Makefile.am b/Makefile.am
index 9c789ced2..f92f45d75 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -306,6 +306,8 @@ libsystem_a_SOURCES = \
libevent_a_SOURCES = \
src/event/WakeFD.hxx \
+ src/event/PollGroup.hxx \
+ src/event/PollGroupEPoll.hxx \
src/event/SignalMonitor.hxx src/event/SignalMonitor.cxx \
src/event/TimeoutMonitor.hxx src/event/TimeoutMonitor.cxx \
src/event/IdleMonitor.hxx src/event/IdleMonitor.cxx \
diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx
index ccba7bb45..f7b3df022 100644
--- a/src/event/Loop.cxx
+++ b/src/event/Loop.cxx
@@ -33,9 +33,6 @@ 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());
@@ -60,23 +57,18 @@ EventLoop::Break()
AddCall([this]() { Break(); });
}
-void
-EventLoop::Abandon(SocketMonitor &m)
+bool
+EventLoop::Abandon(int _fd, 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
+ poll_result.Clear(&m);
+ return poll_group.Abandon(_fd);
}
bool
EventLoop::RemoveFD(int _fd, SocketMonitor &m)
{
-#ifdef USE_EPOLL
- Abandon(m);
- return epoll.Remove(_fd);
-#endif
+ poll_result.Clear(&m);
+ return poll_group.Remove(_fd);
}
void
@@ -168,34 +160,29 @@ EventLoop::Run()
timeout */
continue;
-#ifdef USE_EPOLL
/* wait for new event */
- const int n = epoll.Wait(events, MAX_EVENTS, timeout_ms);
- n_events = std::max(n, 0);
+ poll_group.ReadEvents(poll_result, timeout_ms);
now_ms = ::MonotonicClockMS();
assert(!quit);
/* invoke sockets */
-
- for (int i = 0; i < n; ++i) {
- const auto &e = events[i];
-
- if (e.events != 0) {
- SocketMonitor &m = *(SocketMonitor *)e.data.ptr;
- m.Dispatch(e.events);
+ for (int i = 0; i < poll_result.GetSize(); ++i) {
+ auto events = poll_result.GetEvents(i);
+ if (events != 0) {
+ auto m = (SocketMonitor *)poll_result.GetObject(i);
+ m->Dispatch(events);
if (quit)
break;
}
}
- n_events = 0;
-#endif
- } while (!quit);
+ poll_result.Reset();
+ } while (!quit);
#endif
#ifdef USE_GLIB_EVENTLOOP
diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx
index f188c7cc0..029d01245 100644
--- a/src/event/Loop.hxx
+++ b/src/event/Loop.hxx
@@ -25,10 +25,7 @@
#include "Compiler.h"
#ifdef USE_INTERNAL_EVENTLOOP
-#ifdef USE_EPOLL
-#include "system/EPollFD.hxx"
-#endif
-
+#include "PollGroup.hxx"
#include "thread/Mutex.hxx"
#include "WakeFD.hxx"
#include "SocketMonitor.hxx"
@@ -99,13 +96,8 @@ class EventLoop final
bool quit;
-#ifdef USE_EPOLL
- EPollFD epoll;
- static constexpr unsigned MAX_EVENTS = 16;
- unsigned n_events;
- epoll_event events[MAX_EVENTS];
-#endif
-
+ PollGroup poll_group;
+ PollResult poll_result;
#endif
#ifdef USE_GLIB_EVENTLOOP
@@ -140,15 +132,11 @@ public:
void Break();
bool AddFD(int _fd, unsigned flags, SocketMonitor &m) {
-#ifdef USE_EPOLL
- return epoll.Add(_fd, flags, &m);
-#endif
+ return poll_group.Add(_fd, flags, &m);
}
bool ModifyFD(int _fd, unsigned flags, SocketMonitor &m) {
-#ifdef USE_EPOLL
- return epoll.Modify(_fd, flags, &m);
-#endif
+ return poll_group.Modify(_fd, flags, &m);
}
/**
@@ -156,7 +144,7 @@ public:
* has been closed. This is like RemoveFD(), but does not
* attempt to use #EPOLL_CTL_DEL.
*/
- void Abandon(SocketMonitor &m);
+ bool Abandon(int fd, SocketMonitor &m);
bool RemoveFD(int fd, SocketMonitor &m);
diff --git a/src/event/PollGroup.hxx b/src/event/PollGroup.hxx
new file mode 100644
index 000000000..824a6ecfe
--- /dev/null
+++ b/src/event/PollGroup.hxx
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2003-2013 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_POLLGROUP_HXX
+#define MPD_EVENT_POLLGROUP_HXX
+
+#ifdef USE_EPOLL
+#include "PollGroupEPoll.hxx"
+typedef PollResultEPoll PollResult;
+typedef PollGroupEPoll PollGroup;
+#endif
+
+#endif
diff --git a/src/event/PollGroupEPoll.hxx b/src/event/PollGroupEPoll.hxx
new file mode 100644
index 000000000..5d50cef93
--- /dev/null
+++ b/src/event/PollGroupEPoll.hxx
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2003-2013 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_POLLGROUP_EPOLL_HXX
+#define MPD_EVENT_POLLGROUP_EPOLL_HXX
+
+#include "check.h"
+
+#include "Compiler.h"
+#include "system/EPollFD.hxx"
+
+#include <array>
+#include <algorithm>
+
+class PollResultEPoll
+{
+ friend class PollGroupEPoll;
+
+ std::array<epoll_event, 16> events;
+ int n_events;
+public:
+ PollResultEPoll() : n_events(0) { }
+
+ int GetSize() const { return n_events; }
+ unsigned GetEvents(int i) { return events[i].events; }
+ void *GetObject(int i) { return events[i].data.ptr; }
+ void Reset() { n_events = 0; }
+
+ void Clear(void *obj) {
+ for (int i = 0; i < n_events; ++i)
+ if (events[i].data.ptr == obj)
+ events[i].events = 0;
+ }
+};
+
+class PollGroupEPoll
+{
+ EPollFD epoll;
+
+ PollGroupEPoll(PollGroupEPoll &) = delete;
+ PollGroupEPoll &operator=(PollGroupEPoll &) = delete;
+public:
+ static constexpr unsigned READ = EPOLLIN;
+ static constexpr unsigned WRITE = EPOLLOUT;
+ static constexpr unsigned ERROR = EPOLLERR;
+ static constexpr unsigned HANGUP = EPOLLHUP;
+
+ PollGroupEPoll() = default;
+
+ void ReadEvents(PollResultEPoll &result, int timeout_ms) {
+ int ret = epoll.Wait(result.events.data(), result.events.size(),
+ timeout_ms);
+ result.n_events = std::max(0, ret);
+ }
+
+ bool Add(int fd, unsigned events, void *obj) {
+ return epoll.Add(fd, events, obj);
+ }
+
+ bool Modify(int fd, unsigned events, void *obj) {
+ return epoll.Modify(fd, events, obj);
+ }
+
+ bool Remove(int fd) {
+ return epoll.Remove(fd);
+ }
+
+ bool Abandon(gcc_unused int fd) {
+ // Nothing to do in this implementation.
+ // Closed descriptors are automatically unregistered.
+ return true;
+ }
+};
+
+#endif
diff --git a/src/event/SocketMonitor.cxx b/src/event/SocketMonitor.cxx
index e88427d53..769efba82 100644
--- a/src/event/SocketMonitor.cxx
+++ b/src/event/SocketMonitor.cxx
@@ -158,8 +158,9 @@ SocketMonitor::Abandon()
assert(IsDefined());
#ifdef USE_INTERNAL_EVENTLOOP
+ int old_fd = fd;
fd = -1;
- loop.Abandon(*this);
+ loop.Abandon(old_fd, *this);
#else
Steal();
#endif
diff --git a/src/event/SocketMonitor.hxx b/src/event/SocketMonitor.hxx
index 4d3e5aea2..f6aac2bd6 100644
--- a/src/event/SocketMonitor.hxx
+++ b/src/event/SocketMonitor.hxx
@@ -23,9 +23,7 @@
#include "check.h"
#ifdef USE_INTERNAL_EVENTLOOP
-#ifdef USE_EPOLL
-#include <sys/epoll.h>
-#endif
+#include "PollGroup.hxx"
#endif
#ifdef USE_GLIB_EVENTLOOP
@@ -79,12 +77,10 @@ class SocketMonitor {
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;
-#endif
+ static constexpr unsigned READ = PollGroup::READ;
+ static constexpr unsigned WRITE = PollGroup::WRITE;
+ static constexpr unsigned ERROR = PollGroup::ERROR;
+ static constexpr unsigned HANGUP = PollGroup::HANGUP;
#endif
#ifdef USE_GLIB_EVENTLOOP