From eee873e373b44fd7fbdfdc67f043205b2d22e155 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?=
Date: Tue, 23 Sep 2014 23:31:00 +0200
Subject: [PATCH] Implement idle events
---
utils.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 61 insertions(+), 2 deletions(-)
diff --git a/utils.c b/utils.c
index b1ad86f..380f978 100644
--- a/utils.c
+++ b/utils.c
@@ -851,6 +851,7 @@ xclose (int fd)
typedef void (*poller_fd_fn) (const struct pollfd *, void *);
typedef void (*poller_timer_fn) (void *);
+typedef void (*poller_idle_fn) (void *);
#define POLLER_MIN_ALLOC 16
@@ -877,6 +878,16 @@ struct poller_fd
void *user_data; ///< User data
};
+struct poller_idle
+{
+ LIST_HEADER (poller_idle)
+ struct poller *poller; ///< Our poller
+ bool active; ///< Whether we're on the list
+
+ poller_idle_fn dispatcher; ///< Event dispatcher
+ void *user_data; ///< User data
+};
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
struct poller_timers
@@ -1023,6 +1034,19 @@ poller_timers_get_poll_timeout (struct poller_timers *self)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+static void
+poller_idle_dispatch (struct poller_idle *list)
+{
+ struct poller_idle *iter, *next;
+ for (iter = list; iter; iter = next)
+ {
+ next = iter->next;
+ iter->dispatcher (iter->user_data);
+ }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
#ifdef __linux__
#include
@@ -1035,6 +1059,7 @@ struct poller
size_t alloc; ///< Number of entries allocated
struct poller_timers timers; ///< Timeouts
+ struct poller_idle *idle; ///< Idle events
/// Index of the element in `revents' that's about to be dispatched next.
int dispatch_next;
@@ -1181,7 +1206,7 @@ poller_run (struct poller *self)
int n_fds;
do
n_fds = epoll_wait (self->epoll_fd, self->revents, self->len,
- poller_timers_get_poll_timeout (&self->timers));
+ self->idle ? 0 : poller_timers_get_poll_timeout (&self->timers));
while (n_fds == -1 && errno == EINTR);
if (n_fds == -1)
@@ -1191,6 +1216,7 @@ poller_run (struct poller *self)
self->dispatch_total = n_fds;
poller_timers_dispatch (&self->timers);
+ poller_idle_dispatch (self->idle);
while (self->dispatch_next < self->dispatch_total)
{
@@ -1220,6 +1246,7 @@ struct poller
size_t alloc; ///< Number of entries allocated
struct poller_timers timers; ///< Timers
+ struct poller_idle *idle; ///< Idle events
int dispatch_next; ///< The next dispatched FD or -1
};
@@ -1309,13 +1336,14 @@ poller_run (struct poller *self)
int result;
do
result = poll (self->fds, self->len,
- poller_timers_get_poll_timeout (&self->timers));
+ self->idle ? 0 : poller_timers_get_poll_timeout (&self->timers));
while (result == -1 && errno == EINTR);
if (result == -1)
exit_fatal ("%s: %s", "poll", strerror (errno));
poller_timers_dispatch (&self->timers);
+ poller_idle_dispatch (self->idle);
for (int i = 0; i < (int) self->len; )
{
@@ -1358,6 +1386,37 @@ poller_timer_reset (struct poller_timer *self)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+static void
+poller_idle_init (struct poller_idle *self, struct poller *poller)
+{
+ memset (self, 0, sizeof *self);
+ self->poller = poller;
+}
+
+static void
+poller_idle_set (struct poller_idle *self)
+{
+ if (self->active)
+ return;
+
+ LIST_PREPEND (self->poller->idle, self);
+ self->active = true;
+}
+
+static void
+poller_idle_reset (struct poller_idle *self)
+{
+ if (!self->active)
+ return;
+
+ LIST_UNLINK (self->poller->idle, self);
+ self->prev = NULL;
+ self->next = NULL;
+ self->active = false;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
static void
poller_fd_init (struct poller_fd *self, struct poller *poller, int fd)
{