io: use normal linked lists.
authorRusty Russell <rusty@rustcorp.com.au>
Wed, 27 Aug 2014 06:57:37 +0000 (16:27 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Wed, 27 Aug 2014 06:57:37 +0000 (16:27 +0930)
There seems to be a bug with the overloaded single-linked list.
Rewrite.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/io/backend.h
ccan/io/io.c
ccan/io/poll.c

index 39605ec48662114944f184f4739848e1d2953c0d..3a1f12e7ee859742b0341912de41044c5416b61b 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdbool.h>
 #include <poll.h>
 #include "io_plan.h"
+#include <ccan/list/list.h>
 
 struct fd {
        int fd;
@@ -62,8 +63,8 @@ struct io_conn {
        /* For duplex to save. */
        bool debug_saved;
 
-       /* always or closing list. */
-       struct io_conn *list;
+       /* always and closing lists. */
+       struct list_node always, closing;
 
        void (*finish)(struct io_conn *, void *arg);
        void *finish_arg;
index 0e716fced062c594d42955603e3fcfd2af67d3bb..cd5557d16af9a5d7bf2e3003febfb89237ff7603 100644 (file)
@@ -92,7 +92,8 @@ struct io_conn *io_new_conn_(const tal_t *ctx, int fd,
        conn->fd.fd = fd;
        conn->finish = NULL;
        conn->finish_arg = NULL;
-       conn->list = NULL;
+       list_node_init(&conn->always);
+       list_node_init(&conn->closing);
        conn->debug = false;
 
        if (!add_conn(conn))
index 7af61d5a2699cac1f73aa7470da4da19c37efb9d..3266bdb2f5c737baecde62870445f90597895cfe 100644 (file)
@@ -8,14 +8,14 @@
 #include <sys/socket.h>
 #include <limits.h>
 #include <errno.h>
-#include <ccan/list/list.h>
 #include <ccan/time/time.h>
 #include <ccan/timer/timer.h>
 
 static size_t num_fds = 0, max_fds = 0, num_waiting = 0;
 static struct pollfd *pollfds = NULL;
 static struct fd **fds = NULL;
-static struct io_conn *closing = NULL, *always = NULL;
+static LIST_HEAD(closing);
+static LIST_HEAD(always);
 
 static bool add_fd(struct fd *fd, short events)
 {
@@ -96,31 +96,21 @@ bool add_listener(struct io_listener *l)
 
 void remove_from_always(struct io_conn *conn)
 {
-       struct io_conn **p = &always;
-
-       while (*p != conn)
-               p = &(*p)->list;
-
-       *p = conn->list;
+       list_del_init(&conn->always);
 }
 
 void backend_new_closing(struct io_conn *conn)
 {
-       /* Already on always list?  Remove it. */
-       if (conn->list)
-               remove_from_always(conn);
-
-       conn->list = closing;
-       closing = conn;
+       /* In case it's on always list, remove it. */
+       list_del_init(&conn->always);
+       list_add_tail(&closing, &conn->closing);
 }
 
 void backend_new_always(struct io_conn *conn)
 {
-       /* May already be in always list (other plan), or closing. */
-       if (!conn->list) {
-               conn->list = always;
-               always = conn;
-       }
+       /* In case it's already in always list. */
+       list_del(&conn->always);
+       list_add_tail(&always, &conn->always);
 }
 
 void backend_new_plan(struct io_conn *conn)
@@ -202,14 +192,12 @@ static void accept_conn(struct io_listener *l)
 static bool close_conns(void)
 {
        bool ret = false;
+       struct io_conn *conn;
 
-       while (closing) {
-               struct io_conn *conn = closing;
-
+       while ((conn = list_pop(&closing, struct io_conn, closing)) != NULL) {
                assert(conn->plan[IO_IN].status == IO_CLOSING);
                assert(conn->plan[IO_OUT].status == IO_CLOSING);
 
-               closing = closing->list;
                del_conn(conn);
                ret = true;
        }
@@ -219,16 +207,14 @@ static bool close_conns(void)
 static bool handle_always(void)
 {
        bool ret = false;
+       struct io_conn *conn;
 
-       while (always) {
-               struct io_conn *conn = always;
-
+       while ((conn = list_pop(&always, struct io_conn, always)) != NULL) {
                assert(conn->plan[IO_IN].status == IO_ALWAYS
                       || conn->plan[IO_OUT].status == IO_ALWAYS);
 
-               /* Remove from list, and mark it so it knows that. */
-               always = always->list;
-               conn->list = NULL;
+               /* Re-initialize, for next time. */
+               list_node_init(&conn->always);
                io_do_always(conn);
                ret = true;
        }