From ddc4512d2e0eda6c705e002cb5dbf80719d709e1 Mon Sep 17 00:00:00 2001 From: nicm Date: Sun, 16 Oct 2016 17:55:14 +0000 Subject: Rewrite command queue handling. Each client still has a command queue, but there is also now a global command queue. Instead of command queues being dispatched on demand from wherever the command happens to be added, they are now all dispatched from the top level server loop. Command queues may now also include callbacks as well as commands, and items may be inserted after the current command as well as at the end. This all makes command queues significantly more predictable and easier to use, and avoids the complex multiple nested command queues used by source-file, if-shell and friends. A mass rename of struct cmdq to a better name (cmdq_item probably) is coming. --- tmux.h | 268 +++++++++++++++++++++++++++++++++-------------------------------- 1 file changed, 135 insertions(+), 133 deletions(-) (limited to 'tmux.h') diff --git a/tmux.h b/tmux.h index bbb345b3..b5e5d96c 100644 --- a/tmux.h +++ b/tmux.h @@ -40,6 +40,8 @@ extern char **environ; struct args; struct client; +struct cmd_q; +struct cmd_q_list; struct environ; struct input_ctx; struct mode_key_cmdstr; @@ -631,7 +633,6 @@ struct grid { struct hook { const char *name; - struct cmd_q *cmdq; struct cmd_list *cmdlist; RB_ENTRY(hook) entry; @@ -1160,101 +1161,6 @@ struct message_entry { TAILQ_ENTRY(message_entry) entry; }; -/* Client connection. */ -struct client { - struct tmuxpeer *peer; - - pid_t pid; - int fd; - struct event event; - int retval; - - struct timeval creation_time; - struct timeval activity_time; - - struct environ *environ; - - char *title; - const char *cwd; - - char *term; - char *ttyname; - struct tty tty; - - void (*stdin_callback)(struct client *, int, void *); - void *stdin_callback_data; - struct evbuffer *stdin_data; - int stdin_closed; - struct evbuffer *stdout_data; - struct evbuffer *stderr_data; - - struct event repeat_timer; - - struct event click_timer; - u_int click_button; - - struct event status_timer; - struct screen status; - -#define CLIENT_TERMINAL 0x1 -#define CLIENT_LOGIN 0x2 -#define CLIENT_EXIT 0x4 -#define CLIENT_REDRAW 0x8 -#define CLIENT_STATUS 0x10 -#define CLIENT_REPEAT 0x20 -#define CLIENT_SUSPENDED 0x40 -/* 0x80 unused */ -#define CLIENT_IDENTIFY 0x100 -#define CLIENT_DEAD 0x200 -#define CLIENT_BORDERS 0x400 -#define CLIENT_READONLY 0x800 -#define CLIENT_REDRAWWINDOW 0x1000 -#define CLIENT_CONTROL 0x2000 -#define CLIENT_CONTROLCONTROL 0x4000 -#define CLIENT_FOCUSED 0x8000 -#define CLIENT_UTF8 0x10000 -#define CLIENT_256COLOURS 0x20000 -#define CLIENT_IDENTIFIED 0x40000 -#define CLIENT_STATUSFORCE 0x80000 -#define CLIENT_DOUBLECLICK 0x100000 -#define CLIENT_TRIPLECLICK 0x200000 - int flags; - struct key_table *keytable; - - struct event identify_timer; - void (*identify_callback)(struct client *, struct window_pane *); - void *identify_callback_data; - - char *message_string; - struct event message_timer; - u_int message_next; - TAILQ_HEAD(, message_entry) message_log; - - char *prompt_string; - struct utf8_data *prompt_buffer; - size_t prompt_index; - int (*prompt_callbackfn)(void *, const char *); - void (*prompt_freefn)(void *); - void *prompt_data; - u_int prompt_hindex; - enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode; - -#define PROMPT_SINGLE 0x1 -#define PROMPT_NUMERIC 0x2 - int prompt_flags; - - struct session *session; - struct session *last_session; - - int wlmouse; - - struct cmd_q *cmdq; - int references; - - TAILQ_ENTRY(client) entry; -}; -TAILQ_HEAD(clients, client); - /* Parsed arguments structures. */ struct args_entry; RB_HEAD(args_tree, args_entry); @@ -1324,42 +1230,46 @@ enum cmd_retval { CMD_RETURN_STOP }; -/* Command queue entry. */ -struct cmd_q_item { - struct cmd_list *cmdlist; - - struct mouse_event mouse; - - TAILQ_ENTRY(cmd_q_item) qentry; +/* Command queue item type. */ +enum cmd_q_type { + CMD_Q_COMMAND, + CMD_Q_CALLBACK, }; -TAILQ_HEAD(cmd_q_items, cmd_q_item); -/* Command queue. */ +/* Command queue item. */ +typedef enum cmd_retval (*cmd_q_cb) (struct cmd_q *, void *); struct cmd_q { - int references; - int flags; -#define CMD_Q_DEAD 0x1 -#define CMD_Q_NOHOOKS 0x2 + struct cmd_q_list *queue; + struct cmd_q *next; struct client *client; - int client_exit; - struct cmd_q_items queue; - struct cmd_q_item *item; + enum cmd_q_type type; + u_int group; + + u_int number; + time_t time; + + const char *hook; + int flags; +#define CMD_Q_FIRED 0x1 +#define CMD_Q_WAITING 0x2 +#define CMD_Q_NOHOOKS 0x4 + + struct cmd_list *cmdlist; struct cmd *cmd; - struct cmd_q *parent; + + cmd_q_cb cb; + void *data; struct cmd_find_state current; struct cmd_state state; - time_t time; - u_int number; - - void (*emptyfn)(struct cmd_q *); - void *data; + struct mouse_event mouse; - TAILQ_ENTRY(cmd_q) waitentry; + TAILQ_ENTRY(cmd_q) entry; }; +TAILQ_HEAD(cmd_q_list, cmd_q); /* Command -c, -t or -s flags. */ enum cmd_entry_flag { @@ -1409,6 +1319,101 @@ struct cmd_entry { enum cmd_retval (*exec)(struct cmd *, struct cmd_q *); }; +/* Client connection. */ +struct client { + struct tmuxpeer *peer; + struct cmd_q_list queue; + + pid_t pid; + int fd; + struct event event; + int retval; + + struct timeval creation_time; + struct timeval activity_time; + + struct environ *environ; + + char *title; + const char *cwd; + + char *term; + char *ttyname; + struct tty tty; + + void (*stdin_callback)(struct client *, int, void *); + void *stdin_callback_data; + struct evbuffer *stdin_data; + int stdin_closed; + struct evbuffer *stdout_data; + struct evbuffer *stderr_data; + + struct event repeat_timer; + + struct event click_timer; + u_int click_button; + + struct event status_timer; + struct screen status; + +#define CLIENT_TERMINAL 0x1 +#define CLIENT_LOGIN 0x2 +#define CLIENT_EXIT 0x4 +#define CLIENT_REDRAW 0x8 +#define CLIENT_STATUS 0x10 +#define CLIENT_REPEAT 0x20 +#define CLIENT_SUSPENDED 0x40 +#define CLIENT_ATTACHED 0x80 +#define CLIENT_IDENTIFY 0x100 +#define CLIENT_DEAD 0x200 +#define CLIENT_BORDERS 0x400 +#define CLIENT_READONLY 0x800 +#define CLIENT_REDRAWWINDOW 0x1000 +#define CLIENT_CONTROL 0x2000 +#define CLIENT_CONTROLCONTROL 0x4000 +#define CLIENT_FOCUSED 0x8000 +#define CLIENT_UTF8 0x10000 +#define CLIENT_256COLOURS 0x20000 +#define CLIENT_IDENTIFIED 0x40000 +#define CLIENT_STATUSFORCE 0x80000 +#define CLIENT_DOUBLECLICK 0x100000 +#define CLIENT_TRIPLECLICK 0x200000 + int flags; + struct key_table *keytable; + + struct event identify_timer; + void (*identify_callback)(struct client *, struct window_pane *); + void *identify_callback_data; + + char *message_string; + struct event message_timer; + u_int message_next; + TAILQ_HEAD(, message_entry) message_log; + + char *prompt_string; + struct utf8_data *prompt_buffer; + size_t prompt_index; + int (*prompt_callbackfn)(void *, const char *); + void (*prompt_freefn)(void *); + void *prompt_data; + u_int prompt_hindex; + enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode; + +#define PROMPT_SINGLE 0x1 +#define PROMPT_NUMERIC 0x2 + int prompt_flags; + + struct session *session; + struct session *last_session; + + int wlmouse; + + int references; + + TAILQ_ENTRY(client) entry; +}; +TAILQ_HEAD(clients, client); + /* Key binding and key table. */ struct key_binding { key_code key; @@ -1504,10 +1509,9 @@ void proc_kill_peer(struct tmuxpeer *); /* cfg.c */ extern int cfg_finished; -extern int cfg_references; extern struct client *cfg_client; void start_cfg(void); -int load_cfg(const char *, struct cmd_q *, int); +int load_cfg(const char *, struct client *, struct cmd_q *, int); void set_cfg_file(const char *); void printflike(1, 2) cfg_add_cause(const char *, ...); void cfg_print_causes(struct cmd_q *); @@ -1557,9 +1561,9 @@ void hooks_add(struct hooks *, const char *, struct cmd_list *); void hooks_copy(struct hooks *, struct hooks *); void hooks_remove(struct hooks *, const char *); struct hook *hooks_find(struct hooks *, const char *); -int printflike(4, 5) hooks_run(struct hooks *, struct client *, +void printflike(4, 5) hooks_run(struct hooks *, struct client *, struct cmd_find_state *, const char *, ...); -int printflike(4, 5) hooks_wait(struct hooks *, struct cmd_q *, +void printflike(4, 5) hooks_insert(struct hooks *, struct cmd_q *, struct cmd_find_state *, const char *, ...); /* mode-key.c */ @@ -1755,8 +1759,7 @@ char **cmd_copy_argv(int, char **); void cmd_free_argv(int, char **); char *cmd_stringify_argv(int, char **); struct cmd *cmd_parse(int, char **, const char *, u_int, char **); -int cmd_prepare_state(struct cmd *, struct cmd_q *, - struct cmd_q *); +int cmd_prepare_state(struct cmd *, struct cmd_q *); char *cmd_print(struct cmd *); int cmd_mouse_at(struct window_pane *, struct mouse_event *, u_int *, u_int *, int); @@ -1776,16 +1779,15 @@ void cmd_list_free(struct cmd_list *); char *cmd_list_print(struct cmd_list *); /* cmd-queue.c */ -struct cmd_q *cmdq_new(struct client *); -int cmdq_free(struct cmd_q *); +struct cmd_q *cmdq_get_command(struct cmd_list *, struct cmd_find_state *, + struct mouse_event *, int); +struct cmd_q *cmdq_get_callback(cmd_q_cb, void *); +void cmdq_insert_after(struct cmd_q *, struct cmd_q *); +void cmdq_append(struct client *, struct cmd_q *); +u_int cmdq_next(struct client *); +void cmdq_guard(struct cmd_q *, const char *, int); void printflike(2, 3) cmdq_print(struct cmd_q *, const char *, ...); void printflike(2, 3) cmdq_error(struct cmd_q *, const char *, ...); -void cmdq_guard(struct cmd_q *, const char *, int); -void cmdq_run(struct cmd_q *, struct cmd_list *, - struct mouse_event *); -void cmdq_append(struct cmd_q *, struct cmd_list *, - struct mouse_event *); -int cmdq_continue(struct cmd_q *); /* cmd-string.c */ int cmd_string_parse(const char *, struct cmd_list **, const char *, -- cgit