X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fio%2Fio.h;h=1664df65f26e353120762f1ab89abc65ee01f1c9;hp=1cf9d609973066c04c696f3412fd735ca241bf5d;hb=3f642347378afc9e1db1768d88c9f5b2baffe9ba;hpb=0fbc79090f9ff5bc1caf8c0f0f05525a05f2e82d diff --git a/ccan/io/io.h b/ccan/io/io.h index 1cf9d609..1664df65 100644 --- a/ccan/io/io.h +++ b/ccan/io/io.h @@ -7,6 +7,7 @@ #include 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); @@ -107,7 +109,8 @@ void io_set_finish_(struct io_conn *conn, * @arg: the argument to @init. * * When @fd becomes readable, we accept(), create a new connection, - * (tal'ocated off @ctx) and pass that to init(). + * (tal'ocated off @ctx) and pass that to init(). Note that if there is + * an error on this file descriptor, it will be freed. * * Returns NULL on error (and sets errno). * @@ -452,11 +455,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. @@ -596,14 +596,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) @@ -618,67 +620,67 @@ 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 */ struct io_plan *io_close_cb(struct io_conn *, void *unused); +/** + * io_close_taken_fd - close a connection, but remove the filedescriptor first. + * @conn: the connection to take the file descriptor from and close. + * + * io_close closes the file descriptor underlying the io_conn; this version does + * not. Presumably you have used io_conn_fd() on it beforehand and will take + * care of the fd yourself. + * + * Note that this also turns off O_NONBLOCK on the fd. + * + * Example: + * static struct io_plan *steal_fd(struct io_conn *conn, int *fd) + * { + * *fd = io_conn_fd(conn); + * printf("stealing fd %i and closing\n", *fd); + * return io_close_taken_fd(conn); + * } + */ +struct io_plan *io_close_taken_fd(struct io_conn *conn); + /** * 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. * @conn: the connection. * - * Sometimes useful, eg for getsockname(). + * Sometimes useful, eg for getsockname(). Note that the fd is O_NONBLOCK. + * + * See Also: + * io_close_taken_fd */ 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. - * - * See also: io_debug_complete() + * io_time_override - override the normal call for time. + * @nowfn: the function to call. * - * 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 */