*
* @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)
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.
void *arg);
/**
- * io_idle - plan to do nothing.
+ * io_wait - plan to wait for something.
+ * @wait: the address to wait on.
+ * @cb: function to call after waiting.
+ * @arg: @cb argument
*
- * This indicates the connection is idle: io_wake() will be called later do
- * give the connection a new plan.
+ * This indicates the connection is idle: io_wake() will be called later to
+ * restart the connection.
*
* Example:
* struct io_conn *sleeper;
- * sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
+ * unsigned int counter = 0;
+ * sleeper = io_new_conn(open("/dev/null", O_RDONLY),
+ * io_wait(&counter, io_close_cb, NULL));
* if (!sleeper)
* exit(1);
*/
-#define io_idle() io_debug(io_idle_())
-struct io_plan io_idle_(void);
+#define io_wait(wait, cb, arg) \
+ io_debug(io_wait_(wait, \
+ typesafe_cb_preargs(struct io_plan, void *, \
+ (cb), (arg), \
+ struct io_conn *), \
+ (arg)))
+
+struct io_plan io_wait_(const void *wait,
+ struct io_plan (*cb)(struct io_conn *, void *),
+ void *arg);
/**
* io_timeout - set timeout function if the callback doesn't complete.
struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan);
/**
- * io_wake - wake up an idle connection.
- * @conn: an idle connection.
- * @plan: the next I/O plan for @conn.
- *
- * This makes @conn ready to do I/O the next time around the io_loop().
+ * io_wake - wake up any connections waiting on @wait
+ * @wait: the address to trigger.
*
* Example:
- * struct io_conn *sleeper;
- * sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
- *
- * io_wake(sleeper, io_write("junk", 4, io_close_cb, NULL));
- */
-#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.
+ * unsigned int wait;
*
- * Example:
- * struct io_conn *sleeper;
- * sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
+ * io_new_conn(open("/dev/null", O_RDONLY),
+ * io_wait(&wait, io_close_cb, NULL));
*
- * assert(io_is_idle(sleeper));
- * io_wake(sleeper, io_write("junk", 4, io_close_cb, NULL));
+ * io_wake(&wait);
*/
-bool io_is_idle(const struct io_conn *conn);
+void io_wake(const void *wait);
/**
* io_break - return from io_loop()
#define io_break(ret, plan) (io_plan_no_debug(), io_break_((ret), (plan)))
struct io_plan io_break_(void *ret, struct io_plan plan);
+/**
+ * io_never - assert if callback is called.
+ *
+ * Sometimes you want to make it clear that a callback should never happen
+ * (eg. for io_break). This will assert() if called.
+ *
+ * Example:
+ * static struct io_plan break_out(struct io_conn *conn, void *unused)
+ * {
+ * // We won't ever return from io_break
+ * return io_break(conn, io_never());
+ * }
+ */
+struct io_plan io_never(void);
+
/* FIXME: io_recvfrom/io_sendto */
/**