struct io_conn;
-struct io_state_read {
- char *buf;
- size_t len;
-};
-
-struct io_state_write {
- const char *buf;
- size_t len;
-};
-
-struct io_state_readpart {
- char *buf;
- size_t *lenp;
-};
-
-struct io_state_writepart {
- const char *buf;
- size_t *lenp;
-};
-
-enum io_result {
- RESULT_AGAIN,
- RESULT_FINISHED,
- RESULT_CLOSE
-};
-
/**
* struct io_plan - returned from a setup function.
*
struct io_plan {
int pollflag;
/* Only NULL if idle. */
- enum io_result (*io)(struct io_conn *conn);
+ int (*io)(int fd, struct io_plan *plan);
/* Only NULL if closing. */
struct io_plan (*next)(struct io_conn *, void *arg);
void *next_arg;
union {
- struct io_state_read read;
- struct io_state_write write;
- struct io_state_readpart readpart;
- struct io_state_writepart writepart;
+ struct {
+ char *buf;
+ size_t len;
+ } read;
+ struct {
+ const char *buf;
+ size_t len;
+ } write;
+ struct {
+ char *buf;
+ size_t *lenp;
+ } readpart;
+ struct {
+ const char *buf;
+ size_t *lenp;
+ } writepart;
+ struct {
+ void *p;
+ size_t len;
+ } ptr_len;
+ struct {
+ void *p1;
+ void *p2;
+ } ptr_ptr;
+ struct {
+ size_t len1;
+ size_t len2;
+ } len_len;
} u;
};
+#ifdef DEBUG
+extern bool io_plan_for_other;
+extern bool (*io_debug)(struct io_conn *conn);
+#define io_plan_other() ((io_plan_for_other = true))
+void io_plan_debug(struct io_plan *plan);
+#else
+#define io_plan_other() (void)0
+static inline void io_plan_debug(struct io_plan *plan) { }
+#endif
+
/**
* io_new_conn - create a new connection.
* @fd: the file descriptor.
* @plan: the first I/O function.
- * @finish: the function to call when it's closed or fails.
- * @arg: the argument to @finish.
*
* This creates a connection which owns @fd. @plan will be called on the
- * next io_loop(), and @finish will be called when an I/O operation
- * fails, or you call io_close() on the connection.
+ * next io_loop().
*
* Returns NULL on error (and sets errno).
*/
-#define io_new_conn(fd, plan, finish, arg) \
- io_new_conn_((fd), (plan), \
- typesafe_cb_preargs(void, void *, (finish), (arg), \
- struct io_conn *), \
- (arg))
-struct io_conn *io_new_conn_(int fd,
- struct io_plan plan,
- void (*finish)(struct io_conn *, void *),
- void *arg);
+#define io_new_conn(fd, plan) \
+ (io_plan_other(), io_new_conn_((fd), (plan)))
+struct io_conn *io_new_conn_(int fd, struct io_plan plan);
+
+/**
+ * io_set_finish - set finish function on a connection.
+ * @conn: the connection.
+ * @finish: the function to call when it's closed or fails.
+ * @arg: the argument to @finish.
+ *
+ * @finish will be called when an I/O operation fails, or you call
+ * io_close() on the connection.
+ */
+#define io_set_finish(conn, finish, arg) \
+ io_set_finish_((conn), \
+ typesafe_cb_preargs(void, void *, \
+ (finish), (arg), \
+ struct io_conn *), \
+ (arg))
+void io_set_finish_(struct io_conn *conn,
+ void (*finish)(struct io_conn *, void *),
+ void *arg);
/**
* io_new_listener - create a new accepting listener.
* io_duplex - split an fd into two connections.
* @conn: a connection.
* @plan: the first I/O function to call.
- * @finish: the function to call when it's closed or fails.
- * @arg: the argument to @finish.
*
* Sometimes you want to be able to simultaneously read and write on a
* single fd, but io forces a linear call sequence. The solition is
*
* You must io_close() both of them to close the fd.
*/
-#define io_duplex(conn, plan, finish, arg) \
- io_duplex_((conn), (plan), \
- typesafe_cb_preargs(void, void *, (finish), (arg), \
- struct io_conn *), \
- (arg))
+#define io_duplex(conn, plan) \
+ (io_plan_other(), io_duplex_((conn), (plan)))
-struct io_conn *io_duplex_(struct io_conn *conn,
- struct io_plan plan,
- void (*finish)(struct io_conn *, void *),
- void *arg);
+struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan);
/**
* io_wake - wake up an idle connection.
*
* This makes @conn do I/O the next time around the io_loop().
*/
-void io_wake(struct io_conn *conn, struct io_plan plan);
+#define io_wake(conn, plan) (io_plan_other(), io_wake_((conn), (plan)))
+void io_wake_(struct io_conn *conn, struct io_plan plan);
/**
* io_break - return from io_loop()
*
* If io_loop() is called again, then @plan will be carried out.
*/
-struct io_plan io_break(void *ret, struct io_plan plan);
+#define io_break(ret, plan) (io_plan_other(), io_break_((ret), (plan)))
+struct io_plan io_break_(void *ret, struct io_plan plan);
/* FIXME: io_recvfrom/io_sendto */