]> git.ozlabs.org Git - ccan/blobdiff - ccan/io/io.h
io: update documentation for io_close.
[ccan] / ccan / io / io.h
index d0c0a39a3888526df10c4174ed4dd8e69b8e7153..c1d09963caa9a813bb9560763e1fd07269b8c97f 100644 (file)
@@ -7,6 +7,7 @@
 #include <unistd.h>
 
 struct timers;
+struct timer;
 struct list_head;
 
 /**
@@ -46,7 +47,8 @@ struct io_conn;
  *     int fd[2];
  *     struct io_conn *conn;
  *
- *     pipe(fd);
+ *     if (pipe(fd) != 0)
+ *             exit(1);
  *     conn = io_new_conn(NULL, fd[0], conn_init, (const char *)"hi!");
  *     if (!conn)
  *             exit(1);
@@ -362,6 +364,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 +441,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];
@@ -437,11 +454,8 @@ struct io_plan *io_connect_(struct io_conn *conn, const struct addrinfo *addr,
  *                      io_write(conn, b->out, sizeof(b->out), io_close_cb,b));
  * }
  */
-#define io_duplex(conn, in_plan, out_plan) \
-       (io_duplex_prepare(conn), io_duplex_(in_plan, out_plan))
-
-struct io_plan *io_duplex_(struct io_plan *in_plan, struct io_plan *out_plan);
-void io_duplex_prepare(struct io_conn *conn);
+struct io_plan *io_duplex(struct io_conn *conn,
+                         struct io_plan *in_plan, struct io_plan *out_plan);
 
 /**
  * io_halfclose - close half of an io_duplex connection.
@@ -501,6 +515,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.
@@ -557,14 +595,16 @@ struct io_plan *io_never(struct io_conn *conn, void *unused);
 /* FIXME: io_recvfrom/io_sendto */
 
 /**
- * io_close - plan to close a connection.
+ * io_close - close a connection.
  * @conn: the connection to close.
  *
- * On return to io_loop, the connection will be closed.  It doesn't have
- * to be the current connection and it doesn't need to be idle.  No more
- * IO or callbacks will occur.
+ * The connection is immediately freed: it doesn't have to be the
+ * current connection and it doesn't need to be idle.  No more IO or
+ * callbacks will occur, but if a function was added by io_set_finish()
+ * it will be called with the current errno preserved.
  *
- * You can close a connection twice without harmful effects.
+ * This is equivalent to tal_free(io_conn), except it returns an io_plan
+ * for use in an io callback.
  *
  * Example:
  * static struct io_plan *close_on_timeout(struct io_conn *conn, const char *msg)
@@ -579,8 +619,8 @@ struct io_plan *io_close(struct io_conn *conn);
  * io_close_cb - helper callback to close a connection.
  * @conn: the connection.
  *
- * This schedules a connection to be closed; designed to be used as
- * a callback function.
+ * This is closes a connection; designed to be used as a callback
+ * function.
  *
  * Example:
  *     #define close_on_timeout io_close_cb
@@ -590,16 +630,16 @@ struct io_plan *io_close_cb(struct io_conn *, void *unused);
 /**
  * io_loop - process fds until all closed on io_break.
  * @timers - timers which are waiting to go off (or NULL for none)
- * @expired - a list filled with expired timers (can be NULL if @timers is)
+ * @expired - an expired timer (can be NULL if @timers is)
  *
  * This is the core loop; it exits with the io_break() arg, or NULL if
- * all connections and listeners are closed, or with @expired set to a
- * list of expired timers (if @timers isn't NULL).
+ * all connections and listeners are closed, or with @expired set to an
+ * expired timer (if @timers isn't NULL).
  *
  * Example:
  *     io_loop(NULL, NULL);
  */
-void *io_loop(struct timers *timers, struct list_head *expired);
+void *io_loop(struct timers *timers, struct timer **expired);
 
 /**
  * io_conn_fd - get the fd from a connection.
@@ -610,36 +650,13 @@ void *io_loop(struct timers *timers, struct list_head *expired);
 int io_conn_fd(const struct io_conn *conn);
 
 /**
- * io_set_debug - set synchronous mode on a connection.
- * @conn: the connection.
- * @debug: whether to enable or disable debug.
- *
- * Once @debug is true on a connection, all I/O is done synchronously
- * as soon as it is set, until it is unset or @conn is closed.  This
- * makes it easy to debug what's happening with a connection, but note
- * that other connections are starved while this is being done.
+ * io_time_override - override the normal call for time.
+ * @nowfn: the function to call.
  *
- * See also: io_debug_complete()
- *
- * Example:
- * // Dumb init function to set debug and tell conn to close.
- * static struct io_plan *conn_init(struct io_conn *conn, const char *msg)
- * {
- *     io_set_debug(conn, true);
- *     return io_close(conn);
- * }
+ * io usually uses time_mono() internally, but this forces it
+ * to use your function (eg. for debugging).  Returns the old
+ * one.
  */
-void io_set_debug(struct io_conn *conn, bool debug);
+struct timemono (*io_time_override(struct timemono (*now)(void)))(void);
 
-/**
- * io_debug_complete - empty function called when conn is closing/waiting.
- * @conn: the connection.
- *
- * This is for putting a breakpoint onto, when debugging.  It is called
- * when a conn with io_set_debug() true can no longer be synchronous:
- * 1) It is io_close()'d
- * 2) It enters io_wait() (sychronous debug will resume after io_wake())
- * 3) io_break() is called (sychronous debug will resume after io_loop())
- */
-void io_debug_complete(struct io_conn *conn);
 #endif /* CCAN_IO_H */