From 1543d02f96bdf96a067e96742577ea740dda4d89 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 3 Apr 2013 13:49:58 -0700 Subject: [PATCH] Add callbacks that get invoked before the next call to select(), which will allow for a nice fix to https://github.com/fish-shell/fish-shell/issues/608. Eliminate the poll handler, and replace it with this mechanism. --- input_common.cpp | 42 ++++++++++++++++++++++++++++++------------ input_common.h | 8 +++++--- reader.cpp | 14 ++++++++++---- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/input_common.cpp b/input_common.cpp index 084bc4dcd..ef979c3c5 100644 --- a/input_common.cpp +++ b/input_common.cpp @@ -39,6 +39,12 @@ Implementation file for the low level input library /** Characters that have been read and returned by the sequence matching code */ static std::stack > lookahead_list; +/* Queue of pairs of (function pointer, argument) to be invoked */ +typedef std::pair callback_info_t; +typedef std::queue > callback_queue_t; +static callback_queue_t callback_queue; +static void input_flush_callbacks(void); + static bool has_lookahead(void) { return ! lookahead_list.empty(); @@ -64,20 +70,11 @@ static wint_t lookahead_top(void) /** Callback function for handling interrupts on reading */ static int (*interrupt_handler)(); -/** Callback function to be invoked before reading each byte */ -static void (*poll_handler)(); - - void input_common_init(int (*ih)()) { interrupt_handler = ih; } -void input_common_set_poll_callback(void (*handler)(void)) -{ - poll_handler = handler; -} - void input_common_destroy() { @@ -95,9 +92,8 @@ static wint_t readb() do { - /* Invoke any poll handler */ - if (poll_handler) - poll_handler(); + /* Flush callbacks */ + input_flush_callbacks(); fd_set fdset; int fd_max=0; @@ -280,3 +276,25 @@ void input_common_unreadch(wint_t ch) lookahead_push(ch); } +void input_common_add_callback(void (*callback)(void *), void *arg) +{ + ASSERT_IS_MAIN_THREAD(); + callback_queue.push(callback_info_t(callback, arg)); +} + +static void input_flush_callbacks(void) +{ + /* Nothing to do if nothing to do */ + if (callback_queue.empty()) + return; + + /* We move the queue into a local variable, so that events queued up during a callback don't get fired until next round. */ + callback_queue_t local_queue; + std::swap(local_queue, callback_queue); + while (! local_queue.empty()) + { + const callback_info_t &callback = local_queue.front(); + callback.first(callback.second); //cute + local_queue.pop(); + } +} diff --git a/input_common.h b/input_common.h index 7af527613..02b7359eb 100644 --- a/input_common.h +++ b/input_common.h @@ -30,9 +30,6 @@ enum */ void input_common_init(int (*ih)()); -/* Sets a callback to be invoked every time a byte is read */ -void input_common_set_poll_callback(void (*handler)(void)); - /** Free memory used by the library */ @@ -56,4 +53,9 @@ wchar_t input_common_readch(int timed); */ void input_common_unreadch(wint_t ch); +/** Adds a callback to be invoked at the next turn of the "event loop." The callback function will be invoked and passed arg. */ +void input_common_add_callback(void (*callback)(void *), void *arg); + + + #endif diff --git a/reader.cpp b/reader.cpp index 0f47de69b..17c3583ce 100644 --- a/reader.cpp +++ b/reader.cpp @@ -815,9 +815,6 @@ void reader_init() #ifdef VDSUSP shell_modes.c_cc[VDSUSP] = _POSIX_VDISABLE; #endif - - /* Repaint if necessary before each byte is read. This lets us react immediately to universal variable color changes. */ - input_common_set_poll_callback(reader_repaint_if_needed); } @@ -868,12 +865,21 @@ void reader_repaint_if_needed() } } +static void reader_repaint_if_needed_one_arg(void * unused) +{ + reader_repaint_if_needed(); +} + void reader_react_to_color_change() { - if (data) + if (! data) + return; + + if (! data->repaint_needed || ! data->screen_reset_needed) { data->repaint_needed = true; data->screen_reset_needed = true; + input_common_add_callback(reader_repaint_if_needed_one_arg, NULL); } }