#include <unistd.h>
struct timers;
+struct timer;
struct list_head;
/**
* int fd[2];
* struct io_conn *conn;
*
- * pipe(fd);
+ * if (pipe(fd) != 0)
+ * exit(1);
* conn = io_new_conn(NULL, fd[0], conn_init, (const char *)"hi!");
* if (!conn)
* exit(1);
struct io_plan *(*next)(struct io_conn *, void *),
void *arg);
+/**
+ * io_out_always - output plan to immediately call next callback
+ * @conn: the connection that plan is for.
+ * @next: function to call.
+ * @arg: @next argument
+ *
+ * This is a variant of io_always() which uses the output plan; it only
+ * matters if you are using io_duplex, and thus have two plans running at
+ * once.
+ */
+#define io_out_always(conn, next, arg) \
+ io_out_always_((conn), typesafe_cb_preargs(struct io_plan *, void *, \
+ (next), (arg), \
+ struct io_conn *), \
+ (arg))
+
+struct io_plan *io_out_always_(struct io_conn *conn,
+ struct io_plan *(*next)(struct io_conn *,
+ void *),
+ void *arg);
+
/**
* io_connect - create an asynchronous connection to a listening socket.
* @conn: the connection that plan is for.
*
* 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];
struct io_plan *io_duplex_(struct io_plan *in_plan, struct io_plan *out_plan);
void io_duplex_prepare(struct io_conn *conn);
+/**
+ * io_halfclose - close half of an io_duplex connection.
+ * @conn: the connection that plan is for.
+ *
+ * It's common to want to close a duplex connection after both input and
+ * output plans have completed. If either calls io_close() the connection
+ * closes immediately. Instead, io_halfclose() needs to be called twice.
+ *
+ * Example:
+ * struct buf {
+ * char in[100];
+ * char out[100];
+ * };
+ *
+ * static struct io_plan *finish(struct io_conn *conn, struct buf *b)
+ * {
+ * return io_halfclose(conn);
+ * }
+ *
+ * static struct io_plan *read_and_write(struct io_conn *conn, struct buf *b)
+ * {
+ * return io_duplex(conn,
+ * io_read(conn, b->in, sizeof(b->in), finish, b),
+ * io_write(conn, b->out, sizeof(b->out), finish, b));
+ * }
+ */
+struct io_plan *io_halfclose(struct io_conn *conn);
+
/**
* io_wait - leave a plan idle until something wakes us.
* @conn: the connection that plan is for.
void *arg);
+/**
+ * io_out_wait - leave the output plan idle until something wakes us.
+ * @conn: the connection that plan is for.
+ * @waitaddr: the address to wait on.
+ * @next: function to call after waiting.
+ * @arg: @next argument
+ *
+ * io_wait() makes the input plan idle: if you're not using io_duplex it
+ * doesn't matter which plan is waiting. Otherwise, you may need to use
+ * io_out_wait() instead, to specify explicitly that the output plan is
+ * waiting.
+ */
+#define io_out_wait(conn, waitaddr, next, arg) \
+ io_out_wait_((conn), (waitaddr), \
+ typesafe_cb_preargs(struct io_plan *, void *, \
+ (next), (arg), \
+ struct io_conn *), \
+ (arg))
+
+struct io_plan *io_out_wait_(struct io_conn *conn,
+ const void *wait,
+ struct io_plan *(*next)(struct io_conn *, void *),
+ void *arg);
+
/**
* io_wake - wake up any connections waiting on @wait
* @waitaddr: the address to trigger.
/**
* 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)
+ * @expired - an expired timer (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, or with @expired set to a
- * list of expired timers (if @timers isn't NULL).
+ * all connections and listeners are closed, or with @expired set to an
+ * expired timer (if @timers isn't NULL).
*
* Example:
* io_loop(NULL, NULL);
*/
-void *io_loop(struct timers *timers, struct list_head *expired);
+void *io_loop(struct timers *timers, struct timer **expired);
/**
* io_conn_fd - get the fd from a connection.
*/
int io_conn_fd(const struct io_conn *conn);
+/**
+ * io_time_override - override the normal call for time.
+ * @nowfn: the function to call.
+ *
+ * io usually uses time_mono() internally, but this forces it
+ * to use your function (eg. for debugging). Returns the old
+ * one.
+ */
+struct timemono (*io_time_override(struct timemono (*now)(void)))(void);
+
/**
* io_set_debug - set synchronous mode on a connection.
* @conn: the connection.