We can use either empty slot for this, so figure it out internally.
This could cause problems if you want to use it with io_duplex, so
document that.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
*
* // No room? Wait for writer
* if (b->end == sizeof(b->buf))
- * return io_wait(c, b, IO_IN, read_in, b);
+ * return io_wait(c, b, read_in, b);
*
* return io_read_partial(c, b->buf + b->end, sizeof(b->buf) - b->end,
* &b->rlen, read_in, b);
* if (b->end == b->start) {
* if (b->finished)
* return io_close(c);
- * return io_wait(c, b, IO_OUT, write_out, b);
+ * return io_wait(c, b, write_out, b);
* }
*
* return io_write_partial(c, b->buf + b->start, b->end - b->start,
}
struct io_plan *io_always_(struct io_conn *conn,
- enum io_direction dir,
struct io_plan *(*next)(struct io_conn *, void *),
void *arg)
{
- struct io_plan *plan = io_get_plan(conn, dir);
+ struct io_plan *plan;
+
+ /* If we're duplex, we want this on the current plan. Otherwise,
+ * doesn't matter. */
+ if (conn->plan[IO_IN].status == IO_UNSET)
+ plan = io_get_plan(conn, IO_IN);
+ else
+ plan = io_get_plan(conn, IO_OUT);
assert(next);
set_always(conn, plan, next, arg);
}
struct io_plan *io_wait_(struct io_conn *conn,
- const void *wait, enum io_direction dir,
+ const void *wait,
struct io_plan *(*next)(struct io_conn *, void *),
void *arg)
{
- struct io_plan *plan = io_get_plan(conn, dir);
+ struct io_plan *plan;
+
+ /* If we're duplex, we want this on the current plan. Otherwise,
+ * doesn't matter. */
+ if (conn->plan[IO_IN].status == IO_UNSET)
+ plan = io_get_plan(conn, IO_IN);
+ else
+ plan = io_get_plan(conn, IO_OUT);
assert(next);
struct io_plan *io_never(struct io_conn *conn)
{
- return io_always(conn, IO_IN, io_never_called, NULL);
+ return io_always(conn, io_never_called, NULL);
}
int io_conn_fd(const struct io_conn *conn)
#include <stdbool.h>
#include <unistd.h>
-enum io_direction {
- IO_IN,
- IO_OUT
-};
-
/**
* struct io_plan - a plan for input or output.
*
/**
* io_always - plan to immediately call next callback
* @conn: the connection that plan is for.
- * @dir: IO_IN or IO_OUT
* @next: function to call.
* @arg: @next argument
*
* void *unused)
* {
* // Silly example: close on next time around loop.
- * return io_always(conn, IO_IN, io_close_cb, NULL);
+ * return io_always(conn, io_close_cb, NULL);
* }
*/
-#define io_always(conn, dir, next, arg) \
- io_always_((conn), dir, typesafe_cb_preargs(struct io_plan *, void *, \
- (next), (arg), \
- struct io_conn *), \
+#define io_always(conn, next, arg) \
+ io_always_((conn), typesafe_cb_preargs(struct io_plan *, void *, \
+ (next), (arg), \
+ struct io_conn *), \
(arg))
-struct io_plan *io_always_(struct io_conn *conn, enum io_direction dir,
+struct io_plan *io_always_(struct io_conn *conn,
struct io_plan *(*next)(struct io_conn *, void *),
void *arg);
* io_wait - leave a plan idle until something wakes us.
* @conn: the connection that plan is for.
* @waitaddr: the address to wait on.
- * @dir: IO_IN or IO_OUT
* @next: function to call after waiting.
* @arg: @next argument
*
* // Silly example to wait then close.
* static struct io_plan *wait(struct io_conn *conn, void *b)
* {
- * return io_wait(conn, b, IO_IN, io_close_cb, NULL);
+ * return io_wait(conn, b, io_close_cb, NULL);
* }
*/
-#define io_wait(conn, waitaddr, dir, next, arg) \
- io_wait_((conn), (waitaddr), (dir), \
+#define io_wait(conn, waitaddr, next, arg) \
+ io_wait_((conn), (waitaddr), \
typesafe_cb_preargs(struct io_plan *, void *, \
(next), (arg), \
struct io_conn *), \
(arg))
struct io_plan *io_wait_(struct io_conn *conn,
- const void *wait, enum io_direction dir,
+ const void *wait,
struct io_plan *(*next)(struct io_conn *, void *),
void *arg);
IO_CLOSING
};
+enum io_direction {
+ IO_IN,
+ IO_OUT
+};
+
/**
* struct io_plan - one half of I/O to do
* @status: the status of this plan.
ok1(fd2 >= 0);
io_set_finish(io_new_conn(NULL, fd2, init_waker, d), finish_waker, d);
- return io_wait(conn, d, IO_IN, read_buf, d);
+ return io_wait(conn, d, read_buf, d);
}
static int make_listen_fd(const char *port, struct addrinfo **info)
static struct io_plan *setup_waiter(struct io_conn *conn, char *buf)
{
- return io_wait(conn, buf, IO_IN, read_in, buf);
+ return io_wait(conn, buf, read_in, buf);
}
static struct io_plan *wake_and_close(struct io_conn *conn, char *buf)
static struct io_plan *init_waiter(struct io_conn *conn, void *unused)
{
- return io_wait(conn, inbuf, IO_IN, read_buf, NULL);
+ return io_wait(conn, inbuf, read_buf, NULL);
}
int main(void)
io_wake(&buf->writer);
/* I'll wait until you wake me. */
- return io_wait(conn, &buf->reader, IO_IN, read_buf, buf);
+ return io_wait(conn, &buf->reader, read_buf, buf);
}
static struct io_plan *write_buf(struct io_conn *conn, struct buffer *buf)
return io_close(conn);
/* I'll wait until you tell me to write. */
- return io_wait(conn, &buf->writer, IO_OUT, write_buf, buf);
+ return io_wait(conn, &buf->writer, write_buf, buf);
}
static struct io_plan *setup_reader(struct io_conn *conn, struct buffer *buf)
{
- return io_wait(conn, &buf->reader, IO_IN, read_buf, buf);
+ return io_wait(conn, &buf->reader, read_buf, buf);
}
static struct buffer buf[NUM];
static struct io_plan *setup_waiter(struct io_conn *conn, int *status)
{
- return io_wait(conn, status, IO_IN, io_close_cb, NULL);
+ return io_wait(conn, status, io_close_cb, NULL);
}
int main(void)