X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Fio%2Fio_plan.h;h=21a1921734f41e83d2ed836e157e4849496fb8ad;hp=e87011e7d6a193e7591f2cdc44b400cb11b5ef0d;hb=6109a0a6140acbbfe5e998f7d7ea1215f035cb90;hpb=d4af94ec86618e89b449a27590a7b4f8e4365943 diff --git a/ccan/io/io_plan.h b/ccan/io/io_plan.h index e87011e7..21a19217 100644 --- a/ccan/io/io_plan.h +++ b/ccan/io/io_plan.h @@ -4,97 +4,55 @@ struct io_conn; /** - * struct io_plan - a plan of what I/O to do. - * @pollflag: POLLIN or POLLOUT. - * @io: function to call when fd is available for @pollflag. - * @next: function to call after @io returns true. - * @next_arg: argument to @next. - * @u: scratch area for I/O. - * - * When the fd is POLLIN or POLLOUT (according to @pollflag), @io is - * called. If it returns -1, io_close() becomed the new plan (and errno - * is saved). If it returns 1, @next is called, otherwise @io is - * called again when @pollflag is available. - * - * You can use this to write your own io_plan functions. + * union io_plan_arg - scratch space for struct io_plan read/write fns. */ -struct io_plan { - int pollflag; - /* Only NULL if idle. */ - int (*io)(int fd, struct io_plan *plan); - /* Only NULL if closing. */ - struct io_plan (*next)(struct io_conn *, void *arg); - void *next_arg; +union io_plan_arg { + char *cp; + void *vp; + const void *const_vp; + size_t s; + char c[sizeof(size_t)]; +}; - union { - struct { - char *buf; - size_t len; - } read; - struct { - const char *buf; - size_t len; - } write; - struct { - char *buf; - size_t *lenp; - } readpart; - struct { - const char *buf; - size_t *lenp; - } writepart; - struct { - int saved_errno; - } close; - struct { - void *p; - size_t len; - } ptr_len; - struct { - void *p1; - void *p2; - } ptr_ptr; - struct { - size_t len1; - size_t len2; - } len_len; - } u; +enum io_plan_status { + /* As before calling next function. */ + IO_UNSET, + /* Normal. */ + IO_POLLING, + /* Waiting for io_wake */ + IO_WAITING, + /* Always do this. */ + IO_ALWAYS, + /* Closing (both plans will be the same). */ + IO_CLOSING }; -#ifdef DEBUG -/** - * io_debug - routine to select connection(s) to debug. - * - * If this is set, the routine should return true if the connection is a - * debugging candidate. If so, the callchain for I/O operations on this - * connection will be linear, for easier use of a debugger. - */ -extern bool (*io_debug)(struct io_conn *conn); +enum io_direction { + IO_IN, + IO_OUT +}; /** - * io_plan_other - mark the next plan not being for the current connection - * - * Most routines which take a plan are about to apply it to the current - * connection. We (ab)use this pattern for debugging: as soon as such a - * plan is created, it is called, to create a linear call chain. - * - * Some routines, like io_break() and io_wake() take an io_plan, but they - * must not be applied immediately to the current connection, so we call this - * first. + * struct io_plan - one half of I/O to do + * @status: the status of this plan. + * @io: function to call when fd becomes read/writable, returns 0 to be + * called again, 1 if it's finished, and -1 on error (fd will be closed) + * @next: the next function which is called if io returns 1. + * @next_arg: the argument to @next + * @u1, @u2: scratch space for @io. */ -#define io_plan_other() ((io_plan_for_other = true)) +struct io_plan { + enum io_plan_status status; -/** - * io_plan_debug - hook for debugging a plan. - * - * After constructing a plan, call this. If the current connection is being - * debugged, then it will be immediately serviced with this plan. - */ -void io_plan_debug(struct io_plan *plan); -extern bool io_plan_for_other; -#else -#define io_plan_other() (void)0 -static inline void io_plan_debug(struct io_plan *plan) { } -#endif + int (*io)(int fd, struct io_plan *plan); + + struct io_plan *(*next)(struct io_conn *, void *arg); + void *next_arg; + + union io_plan_arg u1, u2; +}; + +/* Helper to get a conn's io_plan. */ +struct io_plan *io_get_plan(struct io_conn *conn, enum io_direction dir); #endif /* CCAN_IO_PLAN_H */