]> git.ozlabs.org Git - ccan/blobdiff - ccan/io/io.h
ccan/io: add io_out_wait() and io_out_always().
[ccan] / ccan / io / io.h
index 1341b6f209010861958dda6de1335e4e8518e161..1cf9d609973066c04c696f3412fd735ca241bf5d 100644 (file)
@@ -362,6 +362,27 @@ struct io_plan *io_always_(struct io_conn *conn,
                           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.
@@ -418,12 +439,6 @@ struct io_plan *io_connect_(struct io_conn *conn, const struct addrinfo *addr,
  *
  * 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];
@@ -443,6 +458,34 @@ struct io_plan *io_connect_(struct io_conn *conn, const struct addrinfo *addr,
 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.
@@ -473,6 +516,30 @@ struct io_plan *io_wait_(struct io_conn *conn,
                         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.