aboutsummaryrefslogtreecommitdiffstats
path: root/src/event/MultiSocketMonitor.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/MultiSocketMonitor.hxx')
-rw-r--r--src/event/MultiSocketMonitor.hxx139
1 files changed, 37 insertions, 102 deletions
diff --git a/src/event/MultiSocketMonitor.hxx b/src/event/MultiSocketMonitor.hxx
index 8ee81a508..b40ee8caa 100644
--- a/src/event/MultiSocketMonitor.hxx
+++ b/src/event/MultiSocketMonitor.hxx
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2003-2013 The Music Player Daemon Project
+ * Copyright (C) 2003-2014 The Music Player Daemon Project
* http://www.musicpd.org
*
* This program is free software; you can redistribute it and/or modify
@@ -21,40 +21,38 @@
#define MPD_MULTI_SOCKET_MONITOR_HXX
#include "check.h"
-#include "Compiler.h"
-
-#ifdef USE_EPOLL
#include "IdleMonitor.hxx"
#include "TimeoutMonitor.hxx"
#include "SocketMonitor.hxx"
-#else
-#include <glib.h>
-#endif
+#include "Compiler.h"
#include <forward_list>
+#include <iterator>
#include <assert.h>
-#include <stdint.h>
#ifdef WIN32
-/* ERRORis a WIN32 macro that poisons our namespace; this is a
- kludge to allow us to use it anyway */
+/* ERROR is a WIN32 macro that poisons our namespace; this is a kludge
+ to allow us to use it anyway */
#ifdef ERROR
#undef ERROR
#endif
#endif
+#ifndef WIN32
+struct pollfd;
+#endif
+
class EventLoop;
/**
- * Monitor multiple sockets.
+ * Similar to #SocketMonitor, but monitors multiple sockets. To use
+ * it, implement the methods PrepareSockets() and DispatchSockets().
+ * In PrepareSockets(), use UpdateSocketList() and AddSocket().
+ * DispatchSockets() will be called if at least one socket is ready.
*/
-class MultiSocketMonitor
-#ifdef USE_EPOLL
- : private IdleMonitor, private TimeoutMonitor
-#endif
+class MultiSocketMonitor : IdleMonitor, TimeoutMonitor
{
-#ifdef USE_EPOLL
class SingleFD final : public SocketMonitor {
MultiSocketMonitor &multi;
@@ -99,93 +97,45 @@ class MultiSocketMonitor
friend class SingleFD;
bool ready, refresh;
-#else
- struct Source {
- GSource base;
-
- MultiSocketMonitor *monitor;
- };
-
- struct SingleFD {
- GPollFD pfd;
-
- constexpr SingleFD(gcc_unused MultiSocketMonitor &m,
- int fd, unsigned events)
- :pfd{fd, gushort(events), 0} {}
-
- constexpr int GetFD() const {
- return pfd.fd;
- }
-
- constexpr unsigned GetEvents() const {
- return pfd.events;
- }
-
- constexpr unsigned GetReturnedEvents() const {
- return pfd.revents;
- }
-
- void SetEvents(unsigned _events) {
- pfd.events = _events;
- }
- };
-
- EventLoop &loop;
- Source *source;
- uint64_t absolute_timeout_us;
-#endif
std::forward_list<SingleFD> fds;
public:
-#ifdef USE_EPOLL
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
- 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
MultiSocketMonitor(EventLoop &_loop);
~MultiSocketMonitor();
-#ifdef USE_EPOLL
using IdleMonitor::GetEventLoop;
-#else
- EventLoop &GetEventLoop() {
- return loop;
- }
-#endif
public:
-#ifndef USE_EPOLL
- gcc_pure
- uint64_t GetTime() const {
- return g_source_get_time(&source->base);
- }
-#endif
-
+ /**
+ * Invalidate the socket list. A call to PrepareSockets() is
+ * scheduled which will then update the list.
+ */
void InvalidateSockets() {
-#ifdef USE_EPOLL
refresh = true;
IdleMonitor::Schedule();
-#else
- /* no-op because GLib always calls the GSource's
- "prepare" method before each poll() anyway */
-#endif
}
void AddSocket(int fd, unsigned events) {
fds.emplace_front(*this, fd, events);
-#ifndef USE_EPOLL
- g_source_add_poll(&source->base, &fds.front().pfd);
-#endif
}
+ /**
+ * Remove all sockets.
+ */
+ void ClearSocketList();
+
+ /**
+ * Update the known sockets by invoking the given function for
+ * each one; its return value is the events bit mask. A
+ * return value of 0 means the socket will be removed from the
+ * list.
+ */
template<typename E>
void UpdateSocketList(E &&e) {
for (auto prev = fds.before_begin(), end = fds.end(),
@@ -198,16 +148,19 @@ public:
i->SetEvents(events);
prev = i;
} else {
-#ifdef USE_EPOLL
- i->Steal();
-#else
- g_source_remove_poll(&source->base, &i->pfd);
-#endif
fds.erase_after(prev);
}
}
}
+#ifndef WIN32
+ /**
+ * Replace the socket list with the given file descriptors.
+ * The given pollfd array will be modified by this method.
+ */
+ void ReplaceSocketList(pollfd *pfds, unsigned n);
+#endif
+
protected:
/**
* @return timeout [ms] or -1 for no timeout
@@ -215,7 +168,6 @@ protected:
virtual int PrepareSockets() = 0;
virtual void DispatchSockets() = 0;
-#ifdef USE_EPOLL
private:
void SetReady() {
ready = true;
@@ -230,23 +182,6 @@ private:
}
virtual void OnIdle() final;
-
-#else
-public:
- /* GSource callbacks */
- static gboolean Prepare(GSource *source, gint *timeout_r);
- static gboolean Check(GSource *source);
- static gboolean Dispatch(GSource *source, GSourceFunc callback,
- gpointer user_data);
-
-private:
- bool Prepare(gint *timeout_r);
- bool Check() const;
-
- void Dispatch() {
- DispatchSockets();
- }
-#endif
};
#endif