changeset 3959:ef5595d6ddec HEAD

Cleanups: Make io_remove() do the linked list updating also for notify handlers. Removed notify_context from struct io, and moved it to a new struct inotify_io.
author Timo Sirainen <tss@iki.fi>
date Sun, 29 Jan 2006 12:55:22 +0200
parents 3e9b43d0cd80
children aeb424e64f24
files src/lib/ioloop-internal.h src/lib/ioloop-notify-dn.c src/lib/ioloop-notify-inotify.c src/lib/ioloop-notify-kqueue.c src/lib/ioloop.c
diffstat 5 files changed, 45 insertions(+), 88 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/ioloop-internal.h	Sun Jan 29 12:32:37 2006 +0200
+++ b/src/lib/ioloop-internal.h	Sun Jan 29 12:55:22 2006 +0200
@@ -20,6 +20,7 @@
 };
 
 struct io {
+	/* use a doubly linked list so that io_remove() is quick */
 	struct io *prev, *next;
 
 	int fd;
@@ -27,8 +28,6 @@
 
 	io_callback_t *callback;
         void *context;
-
-        int notify_context;
 };
 
 struct timeout {
--- a/src/lib/ioloop-notify-dn.c	Sun Jan 29 12:32:37 2006 +0200
+++ b/src/lib/ioloop-notify-dn.c	Sun Jan 29 12:55:22 2006 +0200
@@ -112,9 +112,6 @@
 
 	io->callback = callback;
         io->context = context;
-
-	io->next = ioloop->notifys;
-	ioloop->notifys = io;
 	return io;
 }
 
@@ -122,17 +119,6 @@
 {
 	struct ioloop_notify_handler_context *ctx =
 		ioloop->notify_handler_context;
-	struct io **io_p;
-
-	if (ctx->disabled)
-		return;
-
-	for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) {
-		if (*io_p == io) {
-			*io_p = io->next;
-			break;
-		}
-	}
 
 	if (fcntl(io->fd, F_NOTIFY, 0) < 0)
 		i_error("fcntl(F_NOTIFY, 0) failed: %m");
@@ -141,8 +127,6 @@
 	if (close(io->fd))
 		i_error("close(dnotify) failed: %m");
 
-	p_free(ioloop->pool, io);
-
 	if (ioloop->notifys == NULL)
 		io_remove(&ctx->event_io);
 }
--- a/src/lib/ioloop-notify-inotify.c	Sun Jan 29 12:32:37 2006 +0200
+++ b/src/lib/ioloop-notify-inotify.c	Sun Jan 29 12:55:22 2006 +0200
@@ -19,6 +19,11 @@
 #define INITIAL_INOTIFY_BUFLEN (FILENAME_MAX + sizeof(struct inotify_event))
 #define MAXIMAL_INOTIFY_BUFLEN (32*1024)
 
+struct inotify_io {
+	struct io io;
+	int wd;
+};
+
 struct ioloop_notify_handler_context {
 	int inotify_fd;
 
@@ -62,7 +67,9 @@
 
 	while ((size_t)required_bytes > sizeof(*event)) {
 		for (io = ioloop->notifys; io != NULL; io = io->next) {
-			if (io->notify_context == event->wd) {
+			struct inotify_io *iio = (struct inotify_io *)io;
+
+			if (iio->wd == event->wd) {
 				io->callback(io->context);
 				break;
 			}
@@ -93,7 +100,7 @@
 {
 	struct ioloop_notify_handler_context *ctx =
 		ioloop->notify_handler_context;
-	struct io *io;
+	struct inotify_io *io;
 	int watchdescriptor;
 
 	if (ctx->disabled)
@@ -114,43 +121,26 @@
 				       event_callback, ioloop);
 	}
 
-	io = p_new(ioloop->pool, struct io, 1);
-	io->fd = -1;
+	io = p_new(ioloop->pool, struct inotify_io, 1);
+	io->io.fd = -1;
 
-	io->callback = callback;
-	io->context = context;
-	io->notify_context = watchdescriptor;
-
-	io->next = ioloop->notifys;
-	ioloop->notifys = io;
+	io->io.callback = callback;
+	io->io.context = context;
+	io->wd = watchdescriptor;
 	return io;
 }
 
-void io_loop_notify_remove(struct ioloop *ioloop, struct io *io)
+void io_loop_notify_remove(struct ioloop *ioloop, struct io *_io)
 {
 	struct ioloop_notify_handler_context *ctx =
 		ioloop->notify_handler_context;
-	struct io **io_p;
-
-	if (ctx->disabled)
-		return;
+	struct inotify_io *io = (struct inotify_io *)_io;
 
-	for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) {
-		if (*io_p == io) {
-			*io_p = io->next;
-			break;
-		}
-	}
-
-	if (inotify_rm_watch(ctx->inotify_fd, io->notify_context) < 0)
+	if (inotify_rm_watch(ctx->inotify_fd, io->wd) < 0)
 		i_error("inotify_rm_watch() failed: %m");
 
-	p_free(ioloop->pool, io);
-
-	if (ioloop->notifys == NULL) {
+	if (ioloop->notifys == NULL)
 		io_remove(&ctx->event_io);
-		ctx->event_io = NULL;
-	}
 }
 
 void io_loop_notify_handler_init(struct ioloop *ioloop)
--- a/src/lib/ioloop-notify-kqueue.c	Sun Jan 29 12:32:37 2006 +0200
+++ b/src/lib/ioloop-notify-kqueue.c	Sun Jan 29 12:55:22 2006 +0200
@@ -38,10 +38,8 @@
 		i_fatal("gettimeofday() failed: %m");
 	ioloop_time = ioloop_timeval.tv_sec;
 
-	if (kevent(ctx->kq, NULL, 0, &ev, 1, 0) < 0) {
+	if (kevent(ctx->kq, NULL, 0, &ev, 1, 0) < 0)
 		i_fatal("kevent() failed: %m");
-		return;
-	}
 	io = ev.udata;
 	io->callback(io->context);
 }
@@ -52,7 +50,6 @@
 
 	ctx = ioloop->notify_handler_context =
 		p_new(ioloop->pool, struct ioloop_notify_handler_context, 1);
-	ctx->event_io = NULL;
 	ctx->kq = kqueue();
 	if (ctx->kq < 0)
 		i_fatal("kqueue() in io_loop_notify_handler_init() failed: %m");
@@ -71,22 +68,6 @@
 	p_free(ioloop->pool, ctx);
 }
 
-static void unchain_io (struct ioloop *ioloop, struct io * io)
-{
-	struct io **io_p;
-
-	for (io_p = &ioloop->notifys; *io_p != NULL; io_p = &(*io_p)->next) {
-		if (*io_p == io) {
-			*io_p = io->next;
-			if (io->next != NULL)
-				io->next->prev = io->prev;
-			io->prev = NULL;
-			io->next = NULL;
-			break;
-		}
-	}
-}
-
 struct io *io_loop_notify_add(struct ioloop *ioloop, const char *path,
 			      io_callback_t *callback, void *context)
 {
@@ -129,11 +110,6 @@
 		p_free(ioloop->pool, io);
 		return NULL;
 	}
-	io->next = ioloop->notifys;
-	io->prev = NULL;
-	if (ioloop->notifys != NULL)
-		ioloop->notifys->prev = io;
-	ioloop->notifys = io;
 
 	if (ctx->event_io == NULL) {
 		ctx->event_io =
@@ -155,8 +131,6 @@
 		i_error("kevent(%d) for notify remove failed: %m", io->fd);
 	if (close(io->fd) < 0)
 		i_error("close(%d) failed: %m", io->fd);
-	unchain_io(ioloop, io);
-	p_free(ioloop->pool, io);
 }
 
 #endif
--- a/src/lib/ioloop.c	Sun Jan 29 12:32:37 2006 +0200
+++ b/src/lib/ioloop.c	Sun Jan 29 12:55:22 2006 +0200
@@ -33,7 +33,6 @@
 
 	io_loop_handle_add(current_ioloop, io);
 
-	/* have to append it, or io_destroy() breaks */
 	io->next = current_ioloop->ios;
 	current_ioloop->ios = io;
 
@@ -53,6 +52,12 @@
 	io = io_loop_notify_add(current_ioloop, path, callback, context);
 	if (io != NULL)
 		io->condition |= IO_NOTIFY;
+
+	io->next = current_ioloop->notifys;
+	current_ioloop->notifys = io;
+
+	if (io->next != NULL)
+		io->next->prev = io;
 	return io;
 }
 
@@ -62,24 +67,29 @@
 
 	*_io = NULL;
 
-	if ((io->condition & IO_NOTIFY) != 0) {
-		io_loop_notify_remove(current_ioloop, io);
-		return;
+	/* unlink from linked list */
+	if (io->prev != NULL)
+		io->prev->next = io->next;
+	else {
+		if ((io->condition & IO_NOTIFY) == 0)
+			current_ioloop->ios = io->next;
+		else
+			current_ioloop->notifys = io->next;
 	}
-
-	/* notify the real I/O handler */
-	io_loop_handle_remove(current_ioloop, io);
-
-	if (current_ioloop->next_io == io)
-                current_ioloop->next_io = io->next;
-
-	if (io->prev == NULL)
-		current_ioloop->ios = io->next;
-	else
-		io->prev->next = io->next;
 	if (io->next != NULL)
 		io->next->prev = io->prev;
 
+	if ((io->condition & IO_NOTIFY) == 0) {
+		/* if we got here from an I/O handler callback, make sure we
+		   don't try to handle this one next. */
+		if (current_ioloop->next_io == io)
+			current_ioloop->next_io = io->next;
+
+		io_loop_handle_remove(current_ioloop, io);
+	} else {
+		io_loop_notify_remove(current_ioloop, io);
+	}
+
 	p_free(current_ioloop->pool, io);
 }