dovecot-2.2: ioloop: Added io_set_pending()

dovecot at dovecot.org dovecot at dovecot.org
Thu Apr 3 16:52:23 UTC 2014


details:   http://hg.dovecot.org/dovecot-2.2/rev/d2a6f57e174f
changeset: 17187:d2a6f57e174f
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Apr 03 19:47:49 2014 +0300
description:
ioloop: Added io_set_pending()

diffstat:

 src/lib/ioloop-epoll.c   |   2 +-
 src/lib/ioloop-kqueue.c  |   2 +-
 src/lib/ioloop-poll.c    |   2 +-
 src/lib/ioloop-private.h |   7 +++++++
 src/lib/ioloop-select.c  |   2 +-
 src/lib/ioloop.c         |  42 ++++++++++++++++++++++++++++++++++++++++++
 src/lib/ioloop.h         |   6 ++++++
 7 files changed, 59 insertions(+), 4 deletions(-)

diffs (182 lines):

diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop-epoll.c
--- a/src/lib/ioloop-epoll.c	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop-epoll.c	Thu Apr 03 19:47:49 2014 +0300
@@ -161,7 +161,7 @@
 	i_free(io);
 }
 
-void io_loop_handler_run(struct ioloop *ioloop)
+void io_loop_handler_run_internal(struct ioloop *ioloop)
 {
 	struct ioloop_handler_context *ctx = ioloop->handler_context;
 	struct epoll_event *events;
diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop-kqueue.c
--- a/src/lib/ioloop-kqueue.c	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop-kqueue.c	Thu Apr 03 19:47:49 2014 +0300
@@ -108,7 +108,7 @@
 		i_free(io);
 }
 
-void io_loop_handler_run(struct ioloop *ioloop)
+void io_loop_handler_run_internal(struct ioloop *ioloop)
 {
 	struct ioloop_handler_context *ctx = ioloop->handler_context;
 	struct kevent *events;
diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop-poll.c
--- a/src/lib/ioloop-poll.c	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop-poll.c	Thu Apr 03 19:47:49 2014 +0300
@@ -143,7 +143,7 @@
 	}
 }
 
-void io_loop_handler_run(struct ioloop *ioloop)
+void io_loop_handler_run_internal(struct ioloop *ioloop)
 {
 	struct ioloop_handler_context *ctx = ioloop->handler_context;
         struct pollfd *pollfd;
diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop-private.h
--- a/src/lib/ioloop-private.h	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop-private.h	Thu Apr 03 19:47:49 2014 +0300
@@ -24,6 +24,8 @@
 	io_loop_time_moved_callback_t *time_moved_callback;
 	time_t next_max_time;
 
+	unsigned int io_pending_count;
+
 	unsigned int running:1;
 	unsigned int iolooping:1;
 };
@@ -31,6 +33,9 @@
 struct io {
 	enum io_condition condition;
 	unsigned int source_linenum;
+	/* trigger I/O callback even if OS doesn't think there is input
+	   pending */
+	bool pending;
 
 	io_callback_t *callback;
         void *context;
@@ -79,6 +84,8 @@
 void io_loop_handle_timeouts(struct ioloop *ioloop);
 void io_loop_call_io(struct io *io);
 
+void io_loop_handler_run_internal(struct ioloop *ioloop);
+
 /* I/O handler calls */
 void io_loop_handle_add(struct io_file *io);
 void io_loop_handle_remove(struct io_file *io, bool closed);
diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop-select.c
--- a/src/lib/ioloop-select.c	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop-select.c	Thu Apr 03 19:47:49 2014 +0300
@@ -103,7 +103,7 @@
 	 (FD_ISSET((fd), &(ctx)->tmp_write_fds) && ((cond) & IO_WRITE)) || \
 	 (FD_ISSET((fd), &(ctx)->tmp_except_fds)))
 
-void io_loop_handler_run(struct ioloop *ioloop)
+void io_loop_handler_run_internal(struct ioloop *ioloop)
 {
 	struct ioloop_handler_context *ctx = ioloop->handler_context;
 	struct timeval tv;
diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop.c
--- a/src/lib/ioloop.c	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop.c	Thu Apr 03 19:47:49 2014 +0300
@@ -93,6 +93,11 @@
 	   kqueue code relies on this. */
 	io->callback = NULL;
 
+	if (io->pending) {
+		i_assert(io->ioloop->io_pending_count > 0);
+		io->ioloop->io_pending_count--;
+	}
+
 	if (io->ctx != NULL)
 		io_loop_context_unref(&io->ctx);
 
@@ -118,6 +123,16 @@
 	io_remove_full(io, TRUE);
 }
 
+void io_set_pending(struct io *io)
+{
+	i_assert((io->condition & IO_NOTIFY) == 0);
+
+	if (!io->pending) {
+		io->pending = TRUE;
+		io->ioloop->io_pending_count++;
+	}
+}
+
 static void timeout_update_next(struct timeout *timeout, struct timeval *tv_now)
 {
 	if (tv_now == NULL) {
@@ -382,6 +397,12 @@
 	struct ioloop *ioloop = io->ioloop;
 	unsigned int t_id;
 
+	if (io->pending) {
+		i_assert(ioloop->io_pending_count > 0);
+		ioloop->io_pending_count--;
+		io->pending = FALSE;
+	}
+
 	if (io->ctx != NULL)
 		io_loop_context_activate(io->ctx);
 	t_id = t_push();
@@ -413,6 +434,24 @@
 	ioloop->iolooping = FALSE;
 }
 
+static void io_loop_call_pending(struct ioloop *ioloop)
+{
+	struct io_file *io;
+
+	for (io = ioloop->io_files; ioloop->io_pending_count > 0; ) {
+		ioloop->next_io_file = io->next;
+		if (io->io.pending)
+			io_loop_call_io(&io->io);
+		io = ioloop->next_io_file;
+	}
+}
+
+void io_loop_handler_run(struct ioloop *ioloop)
+{
+	io_loop_handler_run_internal(ioloop);
+	io_loop_call_pending(ioloop);
+}
+
 void io_loop_stop(struct ioloop *ioloop)
 {
         ioloop->running = FALSE;
@@ -484,6 +523,7 @@
 			  io->io.source_linenum, io->fd);
 		io_remove(&_io);
 	}
+	i_assert(ioloop->io_pending_count == 0);
 
 	while ((item = priorityq_pop(ioloop->timeouts)) != NULL) {
 		struct timeout *to = (struct timeout *)item;
@@ -686,6 +726,8 @@
 	new_io = io_add(old_io_file->fd, old_io->condition,
 			old_io->source_linenum,
 			old_io->callback, old_io->context);
+	if (old_io->pending)
+		io_set_pending(new_io);
 	io_remove(_io);
 	return new_io;
 }
diff -r 8328d67e2329 -r d2a6f57e174f src/lib/ioloop.h
--- a/src/lib/ioloop.h	Thu Apr 03 18:21:39 2014 +0300
+++ b/src/lib/ioloop.h	Thu Apr 03 19:47:49 2014 +0300
@@ -67,6 +67,12 @@
    With some backends this simply frees the memory. */
 void io_remove_closed(struct io **io);
 
+/* Make sure the I/O callback is called by io_loop_run() even if there isn't
+   any input actually pending currently as seen by the OS. This may be useful
+   if some of the input has already read into some internal buffer and the
+   caller wants to handle it the same way as if the fd itself had input. */
+void io_set_pending(struct io *io);
+
 /* Timeout handlers */
 struct timeout *
 timeout_add(unsigned int msecs, unsigned int source_linenum,


More information about the dovecot-cvs mailing list