]> git.ozlabs.org Git - ccan/blobdiff - ccan/io/_info
ccanlint: enhance and streamline "output" testing lines.
[ccan] / ccan / io / _info
index e7dfe9da7b817190ab1c97ab3fb2578b6bde07e5..fe49df5c8d0418094b3630af88bc49e5f9493a5b 100644 (file)
@@ -1,17 +1,17 @@
+#include "config.h"
 #include <stdio.h>
 #include <string.h>
-#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.
  *
  * Example:
- * // Given tr A-Z a-z outputs tr a-z a-z
+ * // Given "tr A-Z a-z" outputs tr a-z a-z
  * #include <ccan/io/io.h>
  * #include <ccan/err/err.h>
  * #include <assert.h>
  * #include <signal.h>
  * #include <sys/types.h>
  * #include <sys/wait.h>
+ * #include <string.h>
  *
  * struct buffer {
- *     size_t max, off, rlen;
- *     char *buf;
+ *     bool finished;
+ *     size_t start, end, rlen, wlen;
+ *     char buf[4096];
  * };
  *
- * struct stdin_buffer {
- *     struct io_conn *reader, *writer;
- *     size_t len;
- *     char inbuf[4096];
- * };
- *
- * // 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)
+ * static void finish(struct io_conn *c, struct buffer *b)
  * {
- *     assert(c == b->reader);
- *     b->len = sizeof(b->inbuf);
- *     return io_read_partial(c, b->inbuf, &b->len, wake_writer, b);
+ *     // Mark us finished.
+ *     b->finished = true;
+ *     // Wake writer just in case it's asleep.
+ *     io_wake(b);
  * }
  *
- * static struct io_plan wake_writer(struct io_conn *c, struct stdin_buffer *b)
+ * static struct io_plan *read_in(struct io_conn *c, struct buffer *b)
  * {
- *     assert(c == b->reader);
- *     io_wake(b->writer, write_to_child, b);
- *     return io_idle(c);
- * }
+ *     // Add what we just read.
+ *     b->end += b->rlen;
+ *     assert(b->end <= sizeof(b->buf));
  *
- * static void reader_exit(struct io_conn *c, struct stdin_buffer *b)
- * {
- *     assert(c == b->reader);
- *     io_wake(b->writer, write_to_child, b);
- *     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);
- * }
+ *     // If we just read something, wake writer.
+ *     if (b->rlen != 0)
+ *             io_wake(b);
  *
- * 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);
- * }
+ *     // If buffer is empty, return to start.
+ *     if (b->start == b->end)
+ *             b->start = b->end = 0;
  *
- * static struct io_plan start_writer(struct io_conn *conn,
- *                                   struct stdin_buffer *b)
- * {
- *     assert(conn == b->writer);
- *     return io_idle(conn);
- * }
+ *     // No room?  Wait for writer
+ *     if (b->end == sizeof(b->buf))
+ *             return io_wait(c, b, read_in, b);
  *
- * static void fail_child_write(struct io_conn *conn, struct stdin_buffer *b)
- * {
- *     if (b->reader)
- *             err(1, "Failed writing to child.");
+ *     return io_read_partial(c, b->buf + b->end, sizeof(b->buf) - b->end,
+ *                            &b->rlen, read_in, b);
  * }
  *
- * // This reads from the child and saves it into buffer.
- * static struct io_plan read_from_child(struct io_conn *conn,
- *                                      struct buffer *b)
+ * static struct io_plan *write_out(struct io_conn *c, struct buffer *b)
  * {
- *     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);
+ *     // Remove what we just wrote.
+ *     b->start += b->wlen;
+ *     assert(b->start <= sizeof(b->buf));
+ *
+ *     // If we wrote something, wake writer.
+ *     if (b->wlen != 0)
+ *             io_wake(b);
+ *
+ *     // Nothing to write?  Wait for reader.
+ *     if (b->end == b->start) {
+ *             if (b->finished)
+ *                     return io_close(c);
+ *             return io_wait(c, b, write_out, b);
  *     }
  *
- *     b->rlen = b->max - b->off;
- *     return io_read_partial(conn, b->buf + b->off, &b->rlen,
- *                            read_from_child, b);
+ *     return io_write_partial(c, b->buf + b->start, b->end - b->start,
+ *                             &b->wlen, write_out, 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 stdin_buffer sbuf;
+ *     struct buffer to, from;
  *     int status;
- *     size_t off;
- *     ssize_t ret;
+ *     struct io_conn *reader;
  *
  *     if (argc == 1)
  *             errx(1, "Usage: runner <cmdline>...");
  *     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))
- *             err(1, "Allocating connections");
+ *     // Read from stdin, write to child.
+ *     memset(&to, 0, sizeof(to));
+ *     reader = io_new_conn(NULL, STDIN_FILENO, read_in, &to);
+ *     io_set_finish(reader, finish, &to);
+ *     io_new_conn(NULL, tochild[1], write_out, &to);
  *
- *     io_loop();
- *     wait(&status);
+ *     // Read from child, write to stdout.
+ *     reader = io_new_conn(NULL, fromchild[0], read_in, &from);
+ *     io_set_finish(reader, finish, &from);
+ *     io_new_conn(NULL, STDOUT_FILENO, write_out, &from);
  *
- *     for (off = 0; off < out.off; off += ret) {
- *             ret = write(STDOUT_FILENO, out.buf+off, out.off-off);
- *             if (ret < 0)
- *                     err(1, "Writing stdout");
- *     }
- *     free(out.buf);
+ *     io_loop(NULL, NULL);
+ *     wait(&status);
  *
  *     return WIFEXITED(status) ? WEXITSTATUS(status) : 2;
  * }
@@ -167,8 +133,12 @@ int main(int argc, char *argv[])
                return 1;
 
        if (strcmp(argv[1], "depends") == 0) {
+               printf("ccan/container_of\n");
+               printf("ccan/list\n");
+               printf("ccan/tal\n");
                printf("ccan/time\n");
                printf("ccan/timer\n");
+               printf("ccan/typesafe_cb\n");
                return 0;
        }