X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fio%2Fio.h;h=ecbeb0b093bf6f0c43054b9a67e1233cff41bf66;hp=6248fec02c2e5c5ae3d42e65d80eb8483af1d5aa;hb=710d42d071a10093077d30d6e521f9599a9bc997;hpb=8700faf27fe4cf9554fec2260bdabd67eabf69ae diff --git a/ccan/io/io.h b/ccan/io/io.h index 6248fec0..ecbeb0b0 100644 --- a/ccan/io/io.h +++ b/ccan/io/io.h @@ -39,7 +39,8 @@ struct io_conn *io_new_conn_(int fd, struct io_plan plan); * * @finish will be called when an I/O operation fails, or you call * io_close() on the connection. errno will be set to the value - * after the failed I/O, or at the call to io_close(). + * after the failed I/O, or at the call to io_close(). The fd + * will be closed (unless a duplex) before @finish is called. * * Example: * static void finish(struct io_conn *conn, void *unused) @@ -290,6 +291,29 @@ struct io_plan io_write_partial_(const void *data, size_t *len, struct io_plan (*cb)(struct io_conn *, void*), void *arg); +/** + * io_always - plan to immediately call next callback. + * @cb: function to call. + * @arg: @cb argument + * + * Sometimes it's neater to plan a callback rather than call it directly; + * for example, if you only need to read data for one path and not another. + * + * Example: + * static void start_conn_with_nothing(int fd) + * { + * // Silly example: close on next time around loop. + * io_new_conn(fd, io_always(io_close_cb, NULL)); + * } + */ +#define io_always(cb, arg) \ + io_debug(io_always_(typesafe_cb_preargs(struct io_plan, void *, \ + (cb), (arg), \ + struct io_conn *), \ + (arg))) +struct io_plan io_always_(struct io_plan (*cb)(struct io_conn *, void *), + void *arg); + /** * io_connect - plan to connect to a listening socket. * @fd: file descriptor. @@ -431,6 +455,21 @@ struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan); #define io_wake(conn, plan) (io_plan_no_debug(), io_wake_((conn), (plan))) void io_wake_(struct io_conn *conn, struct io_plan plan); +/** + * io_is_idle - is a connection idle? + * + * This can be useful for complex protocols, eg. where you want a connection + * to send something, so you queue it and wake it if it's idle. + * + * Example: + * struct io_conn *sleeper; + * sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle()); + * + * assert(io_is_idle(sleeper)); + * io_wake(sleeper, io_write("junk", 4, io_close_cb, NULL)); + */ +bool io_is_idle(const struct io_conn *conn); + /** * io_break - return from io_loop() * @ret: non-NULL value to return from io_loop(). @@ -480,6 +519,24 @@ struct io_plan io_close_(void); */ struct io_plan io_close_cb(struct io_conn *, void *unused); +/** + * io_close_other - close different connection next time around the I/O loop. + * @conn: the connection to close. + * + * This is used to force a different connection to close: no more I/O will + * happen on @conn, even if it's pending. + * + * It's a bug to use this on the current connection! + * + * Example: + * static void stop_connection(struct io_conn *conn) + * { + * printf("forcing stop on connection\n"); + * io_close_other(conn); + * } + */ +void io_close_other(struct io_conn *conn); + /** * io_loop - process fds until all closed on io_break. *