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
-};
-
-enum io_state {
- IO_IO,
- IO_NEXT, /* eg starting, woken from idle, return from io_break. */
- IO_IDLE,
- IO_FINISHED
-};
-
/**
* struct io_plan - returned from a setup function.
*
*/
struct io_plan {
int pollflag;
- enum io_state state;
- enum io_result (*io)(struct io_conn *conn);
+ /* Only NULL if idle. */
+ bool (*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.
* 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))
+ (io_plan_other(), 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 *),
* 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))
+ (io_plan_other(), io_duplex_((conn), (plan), \
+ typesafe_cb_preargs(void, void *, \
+ (finish), (arg), \
+ struct io_conn *), \
+ (arg)))
struct io_conn *io_duplex_(struct io_conn *conn,
struct io_plan plan,
*
* 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 */