X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;ds=sidebyside;f=ccan%2Fio%2Fio.h;h=165ff6f63361d395db25a4706d21eec51b5bbb1b;hb=94dd4c2bddd0dc080ad5b85465fa3f45f486967a;hp=00b9b33db5e7884bfc969acee67247818d0cfa75;hpb=6109a0a6140acbbfe5e998f7d7ea1215f035cb90;p=ccan diff --git a/ccan/io/io.h b/ccan/io/io.h index 00b9b33d..165ff6f6 100644 --- a/ccan/io/io.h +++ b/ccan/io/io.h @@ -6,6 +6,9 @@ #include #include +struct timers; +struct list_head; + /** * struct io_plan - a plan for input or output. * @@ -169,7 +172,7 @@ struct io_listener *io_new_listener_(const tal_t *ctx, int fd, * ... * struct io_listener *l = do_listen("8111"); * if (l) { - * io_loop(); + * io_loop(NULL, NULL); * io_close_listener(l); * } */ @@ -403,6 +406,38 @@ struct io_plan *io_connect_(struct io_conn *conn, const struct addrinfo *addr, struct io_plan *(*next)(struct io_conn *, void *), void *arg); +/** + * io_duplex - set plans for both input and output. + * @conn: the connection that plan is for. + * @in: the input plan + * @out: the output plan + * + * Most plans are either for input or output; io_duplex creates a plan + * which does both. This is often used in the init function to create + * two independent streams, though it can be used once on any connection. + * + * Note that if either plan closes the connection, it will be closed. + * + * Note that if one plan is io_wait or io_always, that causes a problem: + * they look at the input and output plan slots to figure out which to + * use, but if the other plan hasn't been evaluated yet, that will fail. + * In this case, you'll need to ensure the other plan is evaluated first, + * eg. "struct io_plan *r = io_read(...); return io_duplex(r, io_always(...))" + * + * Example: + * struct buf { + * char in[100]; + * char out[100]; + * }; + * + * static struct io_plan *read_and_write(struct io_conn *conn, struct buf *b) + * { + * return io_duplex(io_read(conn, b->in, sizeof(b->in), io_close_cb, b), + * io_write(conn, b->out, sizeof(b->out), io_close_cb, b)); + * } + */ +struct io_plan *io_duplex(struct io_plan *in_plan, struct io_plan *out_plan); + /** * io_wait - leave a plan idle until something wakes us. * @conn: the connection that plan is for. @@ -471,6 +506,7 @@ void io_break(const void *ret); /** * io_never - assert if callback is called. * @conn: the connection that plan is for. + * @unused: an unused parameter to make this suitable for use as a callback. * * Sometimes you want to make it clear that a callback should never happen * (eg. for io_break). This will assert() if called. @@ -480,10 +516,10 @@ void io_break(const void *ret); * { * io_break(conn); * // We won't ever return from io_break - * return io_never(conn); + * return io_never(conn, NULL); * } */ -struct io_plan *io_never(struct io_conn *conn); +struct io_plan *io_never(struct io_conn *conn, void *unused); /* FIXME: io_recvfrom/io_sendto */ @@ -520,14 +556,17 @@ struct io_plan *io_close_cb(struct io_conn *, void *unused); /** * io_loop - process fds until all closed on io_break. + * @timers - timers which are waiting to go off (or NULL for none) + * @expired - a list filled with expired timers (can be NULL if @timers is) * * This is the core loop; it exits with the io_break() arg, or NULL if - * all connections and listeners are closed. + * all connections and listeners are closed, or with @expired set to a + * list of expired timers (if @timers isn't NULL). * * Example: - * io_loop(); + * io_loop(NULL, NULL); */ -void *io_loop(void); +void *io_loop(struct timers *timers, struct list_head *expired); /** * io_conn_fd - get the fd from a connection.