From: Rusty Russell Date: Mon, 14 Oct 2013 11:01:16 +0000 (+1030) Subject: ccan/io: io_set_finish() X-Git-Url: https://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=0f16a4197c94bfa84dad56d0cb9a9c20438d0a45 ccan/io: io_set_finish() Rather than insisting on supplying them on every call to io_new_conn(). Also, this way it can be changed on a connection. Signed-off-by: Rusty Russell --- diff --git a/ccan/io/_info b/ccan/io/_info index 0dfb43c6..a96ee669 100644 --- a/ccan/io/_info +++ b/ccan/io/_info @@ -114,10 +114,8 @@ * sbuf.len = sizeof(sbuf.inbuf); * sbuf.reader = io_new_conn(STDIN_FILENO, * io_read_partial(sbuf.inbuf, &sbuf.len, - * wake_writer, &sbuf), - * reader_exit, &sbuf); - * sbuf.writer = io_new_conn(tochild[1], io_idle(), fail_child_write, - * &sbuf); + * wake_writer, &sbuf)); + * sbuf.writer = io_new_conn(tochild[1], io_idle()); * * out.max = 128; * out.off = 0; @@ -125,11 +123,13 @@ * out.buf = malloc(out.max); * from_child = io_new_conn(fromchild[0], * io_read_partial(out.buf, &out.rlen, - * read_from_child, &out), - * NULL, NULL); + * read_from_child, &out)); * if (!sbuf.reader || !sbuf.writer || !from_child) * err(1, "Allocating connections"); * + * io_set_finish(sbuf.reader, reader_exit, &sbuf); + * io_set_finish(sbuf.writer, fail_child_write, &sbuf); + * * io_loop(); * wait(&status); * diff --git a/ccan/io/benchmarks/run-different-speed.c b/ccan/io/benchmarks/run-different-speed.c index 7a95fd84..5ee15ea6 100644 --- a/ccan/io/benchmarks/run-different-speed.c +++ b/ccan/io/benchmarks/run-different-speed.c @@ -152,12 +152,11 @@ int main(int argc, char *argv[]) /* For efficiency, we share client structure */ io_new_conn(ret, io_read(client.request_buffer, REQUEST_SIZE, - write_reply, &client), - NULL, NULL); + write_reply, &client)); } } - io_new_conn(timeout[0], io_read(&buf, 1, do_timeout, &buf), NULL, NULL); + io_new_conn(timeout[0], io_read(&buf, 1, do_timeout, &buf)); close(wake[0]); for (i = 0; i < NUM_CHILDREN; i++) diff --git a/ccan/io/benchmarks/run-length-prefix.c b/ccan/io/benchmarks/run-length-prefix.c index 5eb33acf..d88e3afa 100644 --- a/ccan/io/benchmarks/run-length-prefix.c +++ b/ccan/io/benchmarks/run-length-prefix.c @@ -157,11 +157,11 @@ int main(int argc, char *argv[]) err(1, "Accepting fd"); /* For efficiency, we share buffer */ client->request_buffer = buffer; - io_new_conn(ret, io_read_header(client), NULL, NULL); + io_new_conn(ret, io_read_header(client)); } } - io_new_conn(timeout[0], io_read(&buf, 1, do_timeout, &buf), NULL, NULL); + io_new_conn(timeout[0], io_read(&buf, 1, do_timeout, &buf)); close(wake[0]); for (i = 0; i < NUM_CHILDREN; i++) diff --git a/ccan/io/benchmarks/run-loop.c b/ccan/io/benchmarks/run-loop.c index b0e6b02c..b0d383e8 100644 --- a/ccan/io/benchmarks/run-loop.c +++ b/ccan/io/benchmarks/run-loop.c @@ -66,14 +66,13 @@ int main(void) memset(buf[i].buf, i, sizeof(buf[i].buf)); sprintf(buf[i].buf, "%i-%i", i, i); - buf[i].reader = io_new_conn(last_read, io_idle(), NULL, NULL); + buf[i].reader = io_new_conn(last_read, io_idle()); if (!buf[i].reader) err(1, "Creating reader %i", i); buf[i].writer = io_new_conn(fds[1], io_write(&buf[i].buf, sizeof(buf[i].buf), - poke_reader, &buf[i]), - NULL, NULL); + poke_reader, &buf[i])); if (!buf[i].writer) err(1, "Creating writer %i", i); last_read = fds[0]; @@ -83,13 +82,12 @@ int main(void) i = 0; buf[i].iters = 0; sprintf(buf[i].buf, "%i-%i", i, i); - buf[i].reader = io_new_conn(last_read, io_idle(), NULL, NULL); + buf[i].reader = io_new_conn(last_read, io_idle()); if (!buf[i].reader) err(1, "Creating reader %i", i); buf[i].writer = io_new_conn(last_write, io_write(&buf[i].buf, sizeof(buf[i].buf), - poke_reader, &buf[i]), - NULL, NULL); + poke_reader, &buf[i])); if (!buf[i].writer) err(1, "Creating writer %i", i); diff --git a/ccan/io/io.c b/ccan/io/io.c index b3c4c760..70e4f1b5 100644 --- a/ccan/io/io.c +++ b/ccan/io/io.c @@ -78,10 +78,7 @@ void io_close_listener(struct io_listener *l) free(l); } -struct io_conn *io_new_conn_(int fd, - struct io_plan plan, - void (*finish)(struct io_conn *, void *), - void *arg) +struct io_conn *io_new_conn_(int fd, struct io_plan plan) { struct io_conn *conn = malloc(sizeof(*conn)); @@ -91,8 +88,8 @@ struct io_conn *io_new_conn_(int fd, conn->fd.listener = false; conn->fd.fd = fd; conn->plan = plan; - conn->finish = finish; - conn->finish_arg = arg; + conn->finish = NULL; + conn->finish_arg = NULL; conn->duplex = NULL; conn->timeout = NULL; if (!add_conn(conn)) { @@ -102,10 +99,15 @@ struct io_conn *io_new_conn_(int fd, return conn; } -struct io_conn *io_duplex_(struct io_conn *old, - struct io_plan plan, - void (*finish)(struct io_conn *, void *), - void *arg) +void io_set_finish_(struct io_conn *conn, + void (*finish)(struct io_conn *, void *), + void *arg) +{ + conn->finish = finish; + conn->finish_arg = arg; +} + +struct io_conn *io_duplex_(struct io_conn *old, struct io_plan plan) { struct io_conn *conn; @@ -119,8 +121,8 @@ struct io_conn *io_duplex_(struct io_conn *old, conn->fd.fd = old->fd.fd; conn->plan = plan; conn->duplex = old; - conn->finish = finish; - conn->finish_arg = arg; + conn->finish = NULL; + conn->finish_arg = NULL; conn->timeout = NULL; if (!add_duplex(conn)) { free(conn); diff --git a/ccan/io/io.h b/ccan/io/io.h index 72f80524..5820f877 100644 --- a/ccan/io/io.h +++ b/ccan/io/io.h @@ -67,25 +67,34 @@ static inline void io_plan_debug(struct io_plan *plan) { } * io_new_conn - create a new connection. * @fd: the file descriptor. * @plan: the first I/O function. - * @finish: the function to call when it's closed or fails. - * @arg: the argument to @finish. * * This creates a connection which owns @fd. @plan will be called on the - * next io_loop(), and @finish will be called when an I/O operation - * fails, or you call io_close() on the connection. + * next io_loop(). * * Returns NULL on error (and sets errno). */ -#define io_new_conn(fd, plan, finish, arg) \ - (io_plan_other(), io_new_conn_((fd), (plan), \ - typesafe_cb_preargs(void, void *, \ - (finish), (arg), \ - struct io_conn *), \ - (arg))) -struct io_conn *io_new_conn_(int fd, - struct io_plan plan, - void (*finish)(struct io_conn *, void *), - void *arg); +#define io_new_conn(fd, plan) \ + (io_plan_other(), io_new_conn_((fd), (plan))) +struct io_conn *io_new_conn_(int fd, struct io_plan plan); + +/** + * io_set_finish - set finish function on a connection. + * @conn: the connection. + * @finish: the function to call when it's closed or fails. + * @arg: the argument to @finish. + * + * @finish will be called when an I/O operation fails, or you call + * io_close() on the connection. + */ +#define io_set_finish(conn, finish, arg) \ + io_set_finish_((conn), \ + typesafe_cb_preargs(void, void *, \ + (finish), (arg), \ + struct io_conn *), \ + (arg)) +void io_set_finish_(struct io_conn *conn, + void (*finish)(struct io_conn *, void *), + void *arg); /** * io_new_listener - create a new accepting listener. @@ -241,8 +250,6 @@ bool io_timeout_(struct io_conn *conn, struct timespec ts, * io_duplex - split an fd into two connections. * @conn: a connection. * @plan: the first I/O function to call. - * @finish: the function to call when it's closed or fails. - * @arg: the argument to @finish. * * Sometimes you want to be able to simultaneously read and write on a * single fd, but io forces a linear call sequence. The solition is @@ -251,17 +258,10 @@ bool io_timeout_(struct io_conn *conn, struct timespec ts, * * You must io_close() both of them to close the fd. */ -#define io_duplex(conn, plan, finish, arg) \ - (io_plan_other(), io_duplex_((conn), (plan), \ - typesafe_cb_preargs(void, void *, \ - (finish), (arg), \ - struct io_conn *), \ - (arg))) +#define io_duplex(conn, plan) \ + (io_plan_other(), io_duplex_((conn), (plan))) -struct io_conn *io_duplex_(struct io_conn *conn, - struct io_plan plan, - void (*finish)(struct io_conn *, void *), - void *arg); +struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan); /** * io_wake - wake up an idle connection. diff --git a/ccan/io/test/run-01-start-finish.c b/ccan/io/test/run-01-start-finish.c index 07476969..297dbc6f 100644 --- a/ccan/io/test/run-01-start-finish.c +++ b/ccan/io/test/run-01-start-finish.c @@ -21,8 +21,8 @@ static void init_conn(int fd, int *state) { ok1(*state == 0); (*state)++; - if (!io_new_conn(fd, io_close(NULL, NULL), finish_ok, state)) - abort(); + io_set_finish(io_new_conn(fd, io_close(NULL, NULL)), finish_ok, state); + } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-02-read.c b/ccan/io/test/run-02-read.c index b8c93c36..65dbe4dc 100644 --- a/ccan/io/test/run-02-read.c +++ b/ccan/io/test/run-02-read.c @@ -27,9 +27,9 @@ static void init_conn(int fd, struct data *d) ok1(d->state == 0); d->state++; - if (!io_new_conn(fd, io_read(d->buf, sizeof(d->buf), io_close, d), - finish_ok, d)) - abort(); + io_set_finish(io_new_conn(fd, + io_read(d->buf, sizeof(d->buf), io_close, d)), + finish_ok, d); } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-03-readpartial.c b/ccan/io/test/run-03-readpartial.c index 5e08b1a2..d5411848 100644 --- a/ccan/io/test/run-03-readpartial.c +++ b/ccan/io/test/run-03-readpartial.c @@ -29,9 +29,9 @@ static void init_conn(int fd, struct data *d) d->state++; d->bytes = sizeof(d->buf); - if (!io_new_conn(fd, io_read_partial(d->buf, &d->bytes, io_close, d), - finish_ok, d)) - abort(); + io_set_finish(io_new_conn(fd, + io_read_partial(d->buf, &d->bytes, io_close, d)), + finish_ok, d); } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-04-writepartial.c b/ccan/io/test/run-04-writepartial.c index 681d9d4d..c80238fe 100644 --- a/ccan/io/test/run-04-writepartial.c +++ b/ccan/io/test/run-04-writepartial.c @@ -27,9 +27,9 @@ static void init_conn(int fd, struct data *d) { ok1(d->state == 0); d->state++; - if (!io_new_conn(fd, io_write_partial(d->buf, &d->bytes, io_close, d), - finish_ok, d)) - abort(); + io_set_finish(io_new_conn(fd, + io_write_partial(d->buf, &d->bytes, io_close, d)), + finish_ok, d); } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-05-write.c b/ccan/io/test/run-05-write.c index f8f30ee5..bcbc9cad 100644 --- a/ccan/io/test/run-05-write.c +++ b/ccan/io/test/run-05-write.c @@ -27,9 +27,8 @@ static void init_conn(int fd, struct data *d) { ok1(d->state == 0); d->state++; - if (!io_new_conn(fd, io_write(d->buf, d->bytes, io_close, d), - finish_ok, d)) - abort(); + io_set_finish(io_new_conn(fd, io_write(d->buf, d->bytes, io_close, d)), + finish_ok, d); } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-06-idle.c b/ccan/io/test/run-06-idle.c index 388805a8..b32cbfe2 100644 --- a/ccan/io/test/run-06-idle.c +++ b/ccan/io/test/run-06-idle.c @@ -52,12 +52,14 @@ static void init_conn(int fd, struct data *d) ok1(d->state == 0); d->state++; - idler = io_new_conn(fd, io_idle(), finish_idle, d); + idler = io_new_conn(fd, io_idle()); + io_set_finish(idler, finish_idle, 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, never, NULL), finish_waker, d)); + io_set_finish(io_new_conn(fd2, io_read(idler, 1, never, NULL)), + finish_waker, d); } static int make_listen_fd(const char *port, struct addrinfo **info) @@ -100,7 +102,7 @@ int main(void) int fd, status; /* This is how many tests you plan to run */ - plan_tests(14); + plan_tests(13); d->state = 0; fd = make_listen_fd(PORT, &addrinfo); ok1(fd >= 0); diff --git a/ccan/io/test/run-07-break.c b/ccan/io/test/run-07-break.c index 3ea20bf5..6fcaea34 100644 --- a/ccan/io/test/run-07-break.c +++ b/ccan/io/test/run-07-break.c @@ -33,11 +33,10 @@ static void init_conn(int fd, struct data *d) ok1(d->state == 0); d->state++; - if (!io_new_conn(fd, - io_break(d, - io_read(d->buf, sizeof(d->buf), read_done, d)), - finish_ok, d)) - abort(); + io_set_finish(io_new_conn(fd, + io_break(d, + io_read(d->buf, sizeof(d->buf), read_done, d))), + finish_ok, d); } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-08-hangup-on-idle.c b/ccan/io/test/run-08-hangup-on-idle.c index 364d7943..7463dd98 100644 --- a/ccan/io/test/run-08-hangup-on-idle.c +++ b/ccan/io/test/run-08-hangup-on-idle.c @@ -26,13 +26,12 @@ int main(void) ok1(pipe(fds) == 0); /* Write then close. */ - io_new_conn(fds[1], io_write("hello there world", 16, io_close, NULL), - NULL, NULL); - conn = io_new_conn(fds[0], io_idle(), NULL, NULL); + io_new_conn(fds[1], io_write("hello there world", 16, io_close, NULL)); + conn = io_new_conn(fds[0], io_idle()); /* To avoid assert(num_waiting) */ ok1(pipe(fds2) == 0); - io_new_conn(fds2[0], io_read(buf, 16, io_close, NULL), NULL, NULL); + io_new_conn(fds2[0], io_read(buf, 16, io_close, NULL)); /* After half a second, it will read. */ io_timeout(conn, time_from_msec(500), timeout_wakeup, buf); diff --git a/ccan/io/test/run-08-read-after-hangup.c b/ccan/io/test/run-08-read-after-hangup.c index 95eb651c..56d9a164 100644 --- a/ccan/io/test/run-08-read-after-hangup.c +++ b/ccan/io/test/run-08-read-after-hangup.c @@ -23,9 +23,8 @@ int main(void) plan_tests(3); ok1(pipe(fds) == 0); - conn = io_new_conn(fds[0], io_idle(), NULL, NULL); - io_new_conn(fds[1], io_write("EASYTEST", 8, wake_it, conn), - NULL, NULL); + conn = io_new_conn(fds[0], io_idle()); + io_new_conn(fds[1], io_write("EASYTEST", 8, wake_it, conn)); ok1(io_loop() == NULL); ok1(memcmp(inbuf, "EASYTEST", sizeof(inbuf)) == 0); diff --git a/ccan/io/test/run-10-many.c b/ccan/io/test/run-10-many.c index 1c39635b..b13e1b43 100644 --- a/ccan/io/test/run-10-many.c +++ b/ccan/io/test/run-10-many.c @@ -66,14 +66,13 @@ int main(void) sprintf(buf[i].buf, "%i-%i", i, i); /* Wait for writer to tell us to read. */ - buf[i].reader = io_new_conn(last_read, io_idle(), NULL, &buf[i]); + buf[i].reader = io_new_conn(last_read, io_idle()); if (!buf[i].reader) break; buf[i].writer = io_new_conn(fds[1], io_write(&buf[i].buf, sizeof(buf[i].buf), - poke_reader, &buf[i]), - NULL, &buf[i]); + poke_reader, &buf[i])); if (!buf[i].writer) break; last_read = fds[0]; @@ -84,12 +83,11 @@ int main(void) /* Last one completes the cirle. */ i = 0; sprintf(buf[i].buf, "%i-%i", i, i); - buf[i].reader = io_new_conn(last_read, io_idle(), NULL, NULL); + buf[i].reader = io_new_conn(last_read, io_idle()); ok1(buf[i].reader); buf[i].writer = io_new_conn(last_write, io_write(&buf[i].buf, sizeof(buf[i].buf), - poke_reader, &buf[i]), - NULL, NULL); + poke_reader, &buf[i])); ok1(buf[i].writer); /* They should eventually exit */ diff --git a/ccan/io/test/run-12-bidir.c b/ccan/io/test/run-12-bidir.c index 812c863c..32319232 100644 --- a/ccan/io/test/run-12-bidir.c +++ b/ccan/io/test/run-12-bidir.c @@ -39,10 +39,11 @@ static void init_conn(int fd, struct data *d) memset(d->wbuf, 7, sizeof(d->wbuf)); - conn = io_new_conn(fd, io_read(d->buf, sizeof(d->buf), io_close, d), - finish_ok, d); - ok1(io_duplex(conn, io_write(d->wbuf, sizeof(d->wbuf), write_done, d), - finish_ok, d)); + conn = io_new_conn(fd, io_read(d->buf, sizeof(d->buf), io_close, d)); + io_set_finish(conn, finish_ok, d); + conn = io_duplex(conn, io_write(d->wbuf, sizeof(d->wbuf), write_done, d)); + ok1(conn); + io_set_finish(conn, finish_ok, d); } static int make_listen_fd(const char *port, struct addrinfo **info) diff --git a/ccan/io/test/run-13-all-idle.c b/ccan/io/test/run-13-all-idle.c index 7ad6bfe4..0e7e1565 100644 --- a/ccan/io/test/run-13-all-idle.c +++ b/ccan/io/test/run-13-all-idle.c @@ -17,7 +17,7 @@ int main(void) int fds[2]; ok1(pipe(fds) == 0); - io_new_conn(fds[0], io_idle(), NULL, NULL); + io_new_conn(fds[0], io_idle()); io_loop(); exit(1); } diff --git a/ccan/io/test/run-15-timeout.c b/ccan/io/test/run-15-timeout.c index f8ea6f4c..a3e9526b 100644 --- a/ccan/io/test/run-15-timeout.c +++ b/ccan/io/test/run-15-timeout.c @@ -48,8 +48,8 @@ static void init_conn(int fd, struct data *d) ok1(d->state == 0); d->state++; - conn = io_new_conn(fd, io_read(d->buf, sizeof(d->buf), no_timeout, d), - finish_ok, d); + conn = io_new_conn(fd, io_read(d->buf, sizeof(d->buf), no_timeout, d)); + io_set_finish(conn, finish_ok, d); io_timeout(conn, time_from_usec(d->timeout_usec), timeout, d); } diff --git a/ccan/io/test/run-17-homemade-io.c b/ccan/io/test/run-17-homemade-io.c index 08c081ec..8b6f17ad 100644 --- a/ccan/io/test/run-17-homemade-io.c +++ b/ccan/io/test/run-17-homemade-io.c @@ -92,8 +92,8 @@ static void init_conn(int fd, struct packet *pkt) ok1(pkt->state == 0); pkt->state++; - if (!io_new_conn(fd, io_read_packet(pkt, io_close, pkt), finish_ok, pkt)) - abort(); + io_set_finish(io_new_conn(fd, io_read_packet(pkt, io_close, pkt)), + finish_ok, pkt); } static int make_listen_fd(const char *port, struct addrinfo **info)