X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fio%2F_info;h=235e6ba3d281df8ee8f7576030ceabcc9779e533;hp=e7dfe9da7b817190ab1c97ab3fb2578b6bde07e5;hb=641b511049e5c03d45ada0c3fd829691b173e5d1;hpb=625bae8f5720d3ad3253ea9b26ad68abcd81bde5 diff --git a/ccan/io/_info b/ccan/io/_info index e7dfe9da..235e6ba3 100644 --- a/ccan/io/_info +++ b/ccan/io/_info @@ -3,12 +3,18 @@ #include "config.h" /** - * io - simple library for stateful io handling. + * io - simple library for asynchronous io handling. * - * io provides a simple mechanism to write I/O servers with multiple - * connections. Handling of connections is multiplexed, and function - * indicate what they want written or read, and what follow-on - * function to call on success (or failure). + * io provides a mechanism to write I/O servers with multiple + * connections. Each callback indicates what I/O they plan next + * (eg. read, write). It is also possible to write custom I/O + * plans. + * + * When compiled with DEBUG, control flow is changed so that rather + * than returning to the main io_loop(), plans are executed sequentially + * providing a backtrace showing what has occurred on that connection. + * Which connection(s) do this depends on the user-specified io_debug + * function. * * Example: * // Given tr A-Z a-z outputs tr a-z a-z @@ -34,50 +40,30 @@ * // This reads from stdin. * static struct io_plan wake_writer(struct io_conn *, struct stdin_buffer *); * // This writes the stdin buffer to the child. - * static struct io_plan write_to_child(struct io_conn *c, - * struct stdin_buffer *b); - * static struct io_plan read_stdin(struct io_conn *c, struct stdin_buffer *b) - * { - * assert(c == b->reader); - * b->len = sizeof(b->inbuf); - * return io_read_partial(c, b->inbuf, &b->len, wake_writer, b); - * } + * static struct io_plan wake_reader(struct io_conn *, struct stdin_buffer *); * * static struct io_plan wake_writer(struct io_conn *c, struct stdin_buffer *b) * { * assert(c == b->reader); - * io_wake(b->writer, write_to_child, b); - * return io_idle(c); + * io_wake(b->writer, io_write(b->inbuf, b->len, wake_reader, b)); + * return io_idle(); * } * * static void reader_exit(struct io_conn *c, struct stdin_buffer *b) * { * assert(c == b->reader); - * io_wake(b->writer, write_to_child, b); + * io_wake(b->writer, io_close()); * b->reader = NULL; * } * * static struct io_plan wake_reader(struct io_conn *c, struct stdin_buffer *b) * { * assert(c == b->writer); - * io_wake(b->reader, read_stdin, b); - * return io_idle(c); - * } - * - * static struct io_plan write_to_child(struct io_conn *conn, - * struct stdin_buffer *b) - * { - * assert(conn == b->writer); - * if (!b->reader) - * return io_close(conn, NULL); - * return io_write(conn, b->inbuf, b->len, wake_reader, b); - * } - * - * static struct io_plan start_writer(struct io_conn *conn, - * struct stdin_buffer *b) - * { - * assert(conn == b->writer); - * return io_idle(conn); + * if (!b->reader) + * return io_close(); + * b->len = sizeof(b->inbuf); + * io_wake(b->reader, io_read_partial(b->inbuf, &b->len, wake_writer, b)); + * return io_idle(); * } * * static void fail_child_write(struct io_conn *conn, struct stdin_buffer *b) @@ -92,30 +78,23 @@ * { * b->off += b->rlen; * - * if (b->off == b->max) { - * if (b->max == 0) - * b->max = 128; - * else if (b->max >= 1024*1024) - * b->max += 1024*1024; - * else - * b->max *= 2; - * b->buf = realloc(b->buf, b->max); - * } + * if (b->off == b->max) + * b->buf = realloc(b->buf, b->max *= 2); * * b->rlen = b->max - b->off; - * return io_read_partial(conn, b->buf + b->off, &b->rlen, - * read_from_child, b); + * return io_read_partial(b->buf + b->off, &b->rlen, read_from_child, b); * } * * // Feed a program our stdin, gather its stdout, print that at end. * int main(int argc, char *argv[]) * { * int tochild[2], fromchild[2]; - * struct buffer out = { 0, 0, 0, NULL }; + * struct buffer out; * struct stdin_buffer sbuf; * int status; * size_t off; * ssize_t ret; + * struct io_conn *from_child; * * if (argc == 1) * errx(1, "Usage: runner ..."); @@ -138,13 +117,25 @@ * close(fromchild[1]); * signal(SIGPIPE, SIG_IGN); * - * sbuf.reader = io_new_conn(STDIN_FILENO, read_stdin, reader_exit, &sbuf); - * sbuf.writer = io_new_conn(tochild[1], start_writer, fail_child_write, - * &sbuf); - * if (!sbuf.reader || !sbuf.writer - * || !io_new_conn(fromchild[0], read_from_child, NULL, &out)) + * sbuf.len = sizeof(sbuf.inbuf); + * sbuf.reader = io_new_conn(STDIN_FILENO, + * io_read_partial(sbuf.inbuf, &sbuf.len, + * wake_writer, &sbuf)); + * sbuf.writer = io_new_conn(tochild[1], io_idle()); + * + * out.max = 128; + * out.off = 0; + * out.rlen = 128; + * out.buf = malloc(out.max); + * from_child = io_new_conn(fromchild[0], + * io_read_partial(out.buf, &out.rlen, + * 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); *