X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Fio%2Fio.c;h=734cb3939636acbf0922362915c5c804bcc2cb97;hb=710d42d071a10093077d30d6e521f9599a9bc997;hp=a58b3f01a71f7526dba3f4e69fb987d8ebaea703;hpb=5a510ed5696255910fd42adb47d7c1ffa728a116;p=ccan diff --git a/ccan/io/io.c b/ccan/io/io.c index a58b3f01..734cb393 100644 --- a/ccan/io/io.c +++ b/ccan/io/io.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -232,6 +231,26 @@ bool io_timeout_(struct io_conn *conn, struct timespec ts, return true; } +/* Always done: call the next thing. */ +static int do_always(int fd, struct io_plan *plan) +{ + return 1; +} + +struct io_plan io_always_(struct io_plan (*cb)(struct io_conn *, void *), + void *arg) +{ + struct io_plan plan; + + assert(cb); + plan.io = do_always; + plan.next = cb; + plan.next_arg = arg; + plan.pollflag = POLLALWAYS; + + return plan; +} + /* Returns true if we're finished. */ static int do_write(int fd, struct io_plan *plan) { @@ -252,6 +271,10 @@ struct io_plan io_write_(const void *data, size_t len, struct io_plan plan; assert(cb); + + if (len == 0) + return io_always_(cb, arg); + plan.u1.const_vp = data; plan.u2.s = len; plan.io = do_write; @@ -281,11 +304,16 @@ struct io_plan io_read_(void *data, size_t len, struct io_plan plan; assert(cb); + + if (len == 0) + return io_always_(cb, arg); + plan.u1.cp = data; plan.u2.s = len; plan.io = do_read; plan.next = cb; plan.next_arg = arg; + plan.pollflag = POLLIN; return plan; @@ -309,6 +337,10 @@ struct io_plan io_read_partial_(void *data, size_t *len, struct io_plan plan; assert(cb); + + if (*len == 0) + return io_always_(cb, arg); + plan.u1.cp = data; plan.u2.vp = len; plan.io = do_read_partial; @@ -337,6 +369,10 @@ struct io_plan io_write_partial_(const void *data, size_t *len, struct io_plan plan; assert(cb); + + if (*len == 0) + return io_always_(cb, arg); + plan.u1.const_vp = data; plan.u2.vp = len; plan.io = do_write_partial; @@ -435,6 +471,10 @@ void io_wake_(struct io_conn *conn, struct io_plan plan) void io_ready(struct io_conn *conn) { + /* Beware io_close_other! */ + if (!conn->plan.next) + return; + set_current(conn); switch (conn->plan.io(conn->fd.fd, &conn->plan)) { case -1: /* Failure means a new plan: close up. */ @@ -474,6 +514,12 @@ struct io_plan io_close_cb(struct io_conn *conn, void *arg) return io_close(); } +void io_close_other(struct io_conn *conn) +{ + conn->plan = io_close_(); + backend_plan_changed(conn); +} + /* Exit the loop, returning this (non-NULL) arg. */ struct io_plan io_break_(void *ret, struct io_plan plan) {