]> git.ozlabs.org Git - ccan/blobdiff - ccan/io/io.h
io failtest timer tools: fallout from time changes.
[ccan] / ccan / io / io.h
index b5ffdd243bfd8a1710e551741261bb9159923cff..3bc1c1fae0b0f3a8bfdd0a588b19847a0fcbcd07 100644 (file)
@@ -39,7 +39,8 @@ struct io_conn *io_new_conn_(int fd, struct io_plan plan);
  *
  * @finish will be called when an I/O operation fails, or you call
  * io_close() on the connection.  errno will be set to the value
- * after the failed I/O, or at the call to io_close().
+ * after the failed I/O, or at the call to io_close().  The fd
+ * will be closed (unless a duplex) before @finish is called.
  *
  * Example:
  * static void finish(struct io_conn *conn, void *unused)
@@ -290,6 +291,30 @@ struct io_plan io_write_partial_(const void *data, size_t *len,
                                 struct io_plan (*cb)(struct io_conn *, void*),
                                 void *arg);
 
+/**
+ * io_always - plan to immediately call next callback.
+ * @cb: function to call.
+ * @arg: @cb argument
+ *
+ * Sometimes it's neater to plan a callback rather than call it directly;
+ * for example, if you only need to read data for one path and not another.
+ *
+ * Example:
+ * static void start_conn_with_nothing(int fd)
+ * {
+ *     // Silly example: close on next time around loop.
+ *     io_new_conn(fd, io_always(io_close_cb, NULL));
+ * }
+ */
+#define io_always(cb, arg)                                             \
+       io_debug(io_always_(typesafe_cb_preargs(struct io_plan, void *, \
+                                               (cb), (arg),            \
+                                               struct io_conn *),      \
+                           (arg)))
+struct io_plan io_always_(struct io_plan (*cb)(struct io_conn *, void *),
+                         void *arg);
+
+
 /**
  * io_connect - plan to connect to a listening socket.
  * @fd: file descriptor.
@@ -336,24 +361,37 @@ struct io_plan io_connect_(int fd, const struct addrinfo *addr,
                           void *arg);
 
 /**
- * io_idle - plan to do nothing.
+ * io_wait - plan to wait for something.
+ * @wait: the address to wait on.
+ * @cb: function to call after waiting.
+ * @arg: @cb argument
  *
- * This indicates the connection is idle: io_wake() will be called later do
- * give the connection a new plan.
+ * This indicates the connection is idle: io_wake() will be called later to
+ * restart the connection.
  *
  * Example:
  *     struct io_conn *sleeper;
- *     sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
+ *     unsigned int counter = 0;
+ *     sleeper = io_new_conn(open("/dev/null", O_RDONLY),
+ *                           io_wait(&counter, io_close_cb, NULL));
  *     if (!sleeper)
  *             exit(1);
  */
-#define io_idle() io_debug(io_idle_())
-struct io_plan io_idle_(void);
+#define io_wait(wait, cb, arg)                                         \
+       io_debug(io_wait_(wait,                                         \
+                         typesafe_cb_preargs(struct io_plan, void *,   \
+                                             (cb), (arg),              \
+                                             struct io_conn *),        \
+                         (arg)))
+
+struct io_plan io_wait_(const void *wait,
+                       struct io_plan (*cb)(struct io_conn *, void *),
+                       void *arg);
 
 /**
  * io_timeout - set timeout function if the callback doesn't complete.
  * @conn: the current connection.
- * @ts: how long until the timeout should be called.
+ * @t: how long until the timeout should be called.
  * @cb: callback to call.
  * @arg: argument to @cb.
  *
@@ -381,7 +419,7 @@ struct io_plan io_idle_(void);
                                        (fn), (arg),                    \
                                        struct io_conn *),              \
                    (arg))
-bool io_timeout_(struct io_conn *conn, struct timespec ts,
+bool io_timeout_(struct io_conn *conn, struct timerel t,
                 struct io_plan (*fn)(struct io_conn *, void *), void *arg);
 
 /**
@@ -416,20 +454,18 @@ bool io_timeout_(struct io_conn *conn, struct timespec ts,
 struct io_conn *io_duplex_(struct io_conn *conn, struct io_plan plan);
 
 /**
- * io_wake - wake up an idle connection.
- * @conn: an idle connection.
- * @plan: the next I/O plan for @conn.
- *
- * This makes @conn ready to do I/O the next time around the io_loop().
+ * io_wake - wake up any connections waiting on @wait
+ * @wait: the address to trigger.
  *
  * Example:
- *     struct io_conn *sleeper;
- *     sleeper = io_new_conn(open("/dev/null", O_RDONLY), io_idle());
+ *     unsigned int wait;
  *
- *     io_wake(sleeper, io_write("junk", 4, io_close_cb, NULL));
+ *     io_new_conn(open("/dev/null", O_RDONLY),
+ *                io_wait(&wait, io_close_cb, NULL));
+ *
+ *     io_wake(&wait);
  */
-#define io_wake(conn, plan) (io_plan_no_debug(), io_wake_((conn), (plan)))
-void io_wake_(struct io_conn *conn, struct io_plan plan);
+void io_wake(const void *wait);
 
 /**
  * io_break - return from io_loop()
@@ -451,6 +487,21 @@ void io_wake_(struct io_conn *conn, struct io_plan plan);
 #define io_break(ret, plan) (io_plan_no_debug(), io_break_((ret), (plan)))
 struct io_plan io_break_(void *ret, struct io_plan plan);
 
+/**
+ * io_never - assert if callback is called.
+ *
+ * Sometimes you want to make it clear that a callback should never happen
+ * (eg. for io_break).  This will assert() if called.
+ *
+ * Example:
+ * static struct io_plan break_out(struct io_conn *conn, void *unused)
+ * {
+ *     // We won't ever return from io_break
+ *     return io_break(conn, io_never());
+ * }
+ */
+struct io_plan io_never(void);
+
 /* FIXME: io_recvfrom/io_sendto */
 
 /**
@@ -480,6 +531,24 @@ struct io_plan io_close_(void);
  */
 struct io_plan io_close_cb(struct io_conn *, void *unused);
 
+/**
+ * io_close_other - close different connection next time around the I/O loop.
+ * @conn: the connection to close.
+ *
+ * This is used to force a different connection to close: no more I/O will
+ * happen on @conn, even if it's pending.
+ *
+ * It's a bug to use this on the current connection!
+ *
+ * Example:
+ * static void stop_connection(struct io_conn *conn)
+ * {
+ *     printf("forcing stop on connection\n");
+ *     io_close_other(conn);
+ * }
+ */
+void io_close_other(struct io_conn *conn);
+
 /**
  * io_loop - process fds until all closed on io_break.
  *
@@ -490,4 +559,25 @@ struct io_plan io_close_cb(struct io_conn *, void *unused);
  *     io_loop();
  */
 void *io_loop(void);
+
+/**
+ * io_conn_fd - get the fd from a connection.
+ * @conn: the connection.
+ *
+ * Sometimes useful, eg for getsockname().
+ */
+int io_conn_fd(const struct io_conn *conn);
+
+/**
+ * io_set_alloc - set alloc/realloc/free function for io to use.
+ * @allocfn: allocator function
+ * @reallocfn: reallocator function, ptr may be NULL, size never 0.
+ * @freefn: free function
+ *
+ * By default io uses malloc/realloc/free, and returns NULL if they fail.
+ * You can set your own variants here.
+ */
+void io_set_alloc(void *(*allocfn)(size_t size),
+                 void *(*reallocfn)(void *ptr, size_t size),
+                 void (*freefn)(void *ptr));
 #endif /* CCAN_IO_H */