From: Rusty Russell Date: Mon, 14 Oct 2013 10:58:36 +0000 (+1030) Subject: ccan/io: remove io_state. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=109f8003b603675aec35e5b1fc678ee363e2f30c ccan/io: remove io_state. Use a NULL next pointer instead to indicate a closing connection. Signed-off-by: Rusty Russell --- diff --git a/ccan/io/io.c b/ccan/io/io.c index ef79e410..34886147 100644 --- a/ccan/io/io.c +++ b/ccan/io/io.c @@ -94,6 +94,8 @@ struct io_conn *io_duplex_(struct io_conn *old, bool io_timeout_(struct io_conn *conn, struct timespec ts, struct io_plan (*cb)(struct io_conn *, void *), void *arg) { + assert(cb); + if (!conn->timeout) { conn->timeout = malloc(sizeof(*conn->timeout)); if (!conn->timeout) @@ -128,13 +130,13 @@ struct io_plan io_write_(const void *data, size_t len, { struct io_plan plan; + assert(cb); plan.u.write.buf = data; plan.u.write.len = len; plan.io = do_write; plan.next = cb; plan.next_arg = arg; plan.pollflag = POLLOUT; - plan.state = IO_IO; return plan; } @@ -159,13 +161,13 @@ struct io_plan io_read_(void *data, size_t len, { struct io_plan plan; + assert(cb); plan.u.read.buf = data; plan.u.read.len = len; plan.io = do_read; plan.next = cb; plan.next_arg = arg; plan.pollflag = POLLIN; - plan.state = IO_IO; return plan; } @@ -186,13 +188,13 @@ struct io_plan io_read_partial_(void *data, size_t *len, { struct io_plan plan; + assert(cb); plan.u.readpart.buf = data; plan.u.readpart.lenp = len; plan.io = do_read_partial; plan.next = cb; plan.next_arg = arg; plan.pollflag = POLLIN; - plan.state = IO_IO; return plan; } @@ -214,13 +216,13 @@ struct io_plan io_write_partial_(const void *data, size_t *len, { struct io_plan plan; + assert(cb); plan.u.writepart.buf = data; plan.u.writepart.lenp = len; plan.io = do_write_partial; plan.next = cb; plan.next_arg = arg; plan.pollflag = POLLOUT; - plan.state = IO_IO; return plan; } @@ -230,8 +232,9 @@ struct io_plan io_idle(void) struct io_plan plan; plan.pollflag = 0; - plan.state = IO_IO; plan.io = NULL; + /* Never called (overridded by io_wake), but NULL means closing */ + plan.next = io_close; return plan; } @@ -239,9 +242,10 @@ struct io_plan io_idle(void) void io_wake(struct io_conn *conn, struct io_plan plan) { - /* It might have finished, but we haven't called its finish() yet. */ - if (conn->plan.state == IO_FINISHED) + /* It might be closing, but we haven't called its finish() yet. */ + if (!conn->plan.next) return; + /* It was idle, right? */ assert(!conn->plan.io); conn->plan = plan; backend_wakeup(conn); @@ -256,7 +260,6 @@ static struct io_plan do_next(struct io_conn *conn) struct io_plan do_ready(struct io_conn *conn) { - assert(conn->plan.state == IO_IO); switch (conn->plan.io(conn)) { case RESULT_CLOSE: return io_close(conn, NULL); @@ -275,8 +278,9 @@ struct io_plan io_close(struct io_conn *conn, void *arg) { struct io_plan plan; - plan.state = IO_FINISHED; plan.pollflag = 0; + /* This means we're closing. */ + plan.next = NULL; return plan; } @@ -284,6 +288,7 @@ struct io_plan io_close(struct io_conn *conn, void *arg) /* Exit the loop, returning this (non-NULL) arg. */ struct io_plan io_break(void *ret, struct io_plan plan) { + assert(ret); io_loop_return = ret; return plan; diff --git a/ccan/io/io.h b/ccan/io/io.h index fb6feb4d..cbd2b9be 100644 --- a/ccan/io/io.h +++ b/ccan/io/io.h @@ -34,11 +34,6 @@ enum io_result { RESULT_CLOSE }; -enum io_state { - IO_IO, - IO_FINISHED -}; - /** * struct io_plan - returned from a setup function. * @@ -46,8 +41,9 @@ enum io_state { */ struct io_plan { int pollflag; - enum io_state state; + /* Only NULL if idle. */ enum io_result (*io)(struct io_conn *conn); + /* Only NULL if closing. */ struct io_plan (*next)(struct io_conn *, void *arg); void *next_arg; diff --git a/ccan/io/poll.c b/ccan/io/poll.c index da9107c2..46b2334e 100644 --- a/ccan/io/poll.c +++ b/ccan/io/poll.c @@ -8,7 +8,7 @@ #include #include -static size_t num_fds = 0, max_fds = 0, num_finished = 0, num_waiting = 0; +static size_t num_fds = 0, max_fds = 0, num_closing = 0, num_waiting = 0; static struct pollfd *pollfds = NULL; static struct fd **fds = NULL; static struct timers timeouts; @@ -77,12 +77,6 @@ bool add_listener(struct io_listener *l) return true; } -static void adjust_counts(enum io_state state) -{ - if (state == IO_FINISHED) - num_finished++; -} - static void update_pollevents(struct io_conn *conn) { struct pollfd *pfd = &pollfds[conn->fd.backend_info]; @@ -100,14 +94,17 @@ static void update_pollevents(struct io_conn *conn) if (pfd->events) num_waiting++; - adjust_counts(conn->plan.state); + if (!conn->plan.next) + num_closing++; } bool add_conn(struct io_conn *c) { if (!add_fd(&c->fd, c->plan.pollflag)) return false; - adjust_counts(c->plan.state); + /* Immediate close is allowed. */ + if (!c->plan.next) + num_closing++; return true; } @@ -120,7 +117,6 @@ bool add_duplex(struct io_conn *c) static void del_conn(struct io_conn *conn) { - assert(conn->plan.state == IO_FINISHED); if (conn->finish) conn->finish(conn, conn->finish_arg); if (timeout_active(conn)) @@ -132,7 +128,7 @@ static void del_conn(struct io_conn *conn) conn->duplex->duplex = NULL; } else del_fd(&conn->fd); - num_finished--; + num_closing--; } void del_listener(struct io_listener *l) @@ -169,14 +165,14 @@ static void finish_conns(void) for (i = 0; !io_loop_return && i < num_fds; i++) { struct io_conn *c, *duplex; - if (!num_finished) + if (!num_closing) break; if (fds[i]->listener) continue; c = (void *)fds[i]; for (duplex = c->duplex; c; c = duplex, duplex = NULL) { - if (c->plan.state == IO_FINISHED) { + if (!c->plan.next) { del_conn(c); free(c); i--; @@ -239,7 +235,7 @@ void *io_loop(void) } } - if (num_finished) { + if (num_closing) { finish_conns(); /* Could have started/finished more. */ continue; @@ -290,7 +286,7 @@ void *io_loop(void) } } - while (num_finished) + while (num_closing) finish_conns(); ret = io_loop_return; diff --git a/ccan/io/test/run-06-idle.c b/ccan/io/test/run-06-idle.c index fb681a08..d75a216d 100644 --- a/ccan/io/test/run-06-idle.c +++ b/ccan/io/test/run-06-idle.c @@ -37,6 +37,11 @@ static void finish_idle(struct io_conn *conn, struct data *d) io_break(d, io_idle()); } +static struct io_plan never(struct io_conn *conn, void *arg) +{ + abort(); +} + static void init_conn(int fd, struct data *d) { int fd2; @@ -48,7 +53,7 @@ static void init_conn(int fd, struct data *d) /* This will wake us up, as read will fail. */ fd2 = open("/dev/null", O_RDONLY); ok1(fd2 >= 0); - ok1(io_new_conn(fd2, io_read(idler, 1, NULL, NULL), finish_waker, d)); + ok1(io_new_conn(fd2, io_read(idler, 1, never, NULL), finish_waker, d)); } static int make_listen_fd(const char *port, struct addrinfo **info)