From 52dc415d0be5178308e5f635acddb8a051d4b6c5 Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Tue, 28 Feb 2012 12:40:20 -0800 Subject: [PATCH] Fix to add a generation count to threaded operations so they abort early --- reader.cpp | 75 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/reader.cpp b/reader.cpp index 553b405fa..aa2a44fb9 100644 --- a/reader.cpp +++ b/reader.cpp @@ -174,6 +174,9 @@ commence. */ #define SEARCH_FORWARD 1 +/* Any time the contents of a buffer changes, we update the generation count. This allows for our background highlighting thread to notice it and skip doing work that it would otherwise have to do. */ +static unsigned int s_generation_count; + /* A color is an int */ typedef int color_t; @@ -215,7 +218,7 @@ class reader_data_t int token_history_pos; /** - Saved search string for token history search. Not handled by check_size. + Saved search string for token history search. Not handled by command_line_changed. */ wcstring token_history_buff; @@ -230,8 +233,8 @@ class reader_data_t /** Length of the command */ size_t command_length() const { return command_line.size(); } - /** Ensures that our buffers are the right size */ - void check_size(void); + /** Do what we need to do whenever our command line changes */ + void command_line_changed(void); /** The current position of the cursor in buff. */ size_t buff_pos; @@ -488,7 +491,7 @@ static void reader_kill( size_t begin_idx, int length, int mode, int newv ) } data->command_line.erase(begin_idx, length); - data->check_size(); + data->command_line_changed(); reader_super_highlight_me_plenty( data->buff_pos ); reader_repaint(); @@ -536,10 +539,14 @@ void reader_pop_current_filename() /** Make sure buffers are large enough to hold the current string length */ -void reader_data_t::check_size() { +void reader_data_t::command_line_changed() { + ASSERT_IS_MAIN_THREAD(); size_t len = command_length(); colors.resize(len); indents.resize(len); + + /* Update the gen count */ + s_generation_count++; } @@ -720,7 +727,7 @@ static void remove_backward() data->command_line.erase(data->buff_pos-1, 1); data->buff_pos--; - data->check_size(); + data->command_line_changed(); data->suppress_autosuggestion = true; reader_super_highlight_me_plenty( data->buff_pos ); @@ -737,9 +744,12 @@ static void remove_backward() static int insert_string(const wcstring &str) { size_t len = str.size(); + if (len == 0) + return 0; + data->command_line.insert(data->buff_pos, str); data->buff_pos += len; - data->check_size(); + data->command_line_changed(); data->suppress_autosuggestion = false; /* Syntax highlight */ @@ -1226,6 +1236,7 @@ struct autosuggestion_context_t { const wcstring working_directory; const env_vars vars; wcstring_list_t commands_to_load; + const unsigned int generation_count; // don't reload more than once bool has_tried_reloading; @@ -1236,13 +1247,18 @@ struct autosuggestion_context_t { detector(history, term), working_directory(get_working_directory()), vars(env_vars::highlighting_keys), + generation_count(s_generation_count), has_tried_reloading(false) { } int threaded_autosuggest(void) { ASSERT_IS_BACKGROUND_THREAD(); - + + if (generation_count != s_generation_count) { + return 0; + } + while (searcher.go_backwards()) { history_item_t item = searcher.current_item(); bool item_ok = false; @@ -1294,7 +1310,6 @@ static bool can_autosuggest(void) { static void autosuggest_completed(autosuggestion_context_t *ctx, int result) { - /* Extract the commands to load */ wcstring_list_t commands_to_load; ctx->commands_to_load.swap(commands_to_load); @@ -1818,7 +1833,7 @@ void reader_replace_current_token( const wchar_t *new_token ) static void handle_history( const wcstring &new_str ) { data->command_line = new_str; - data->check_size(); + data->command_line_changed(); data->buff_pos=data->command_line.size(); reader_super_highlight_me_plenty( data->buff_pos ); reader_repaint(); @@ -2146,8 +2161,7 @@ void reader_set_buffer( const wcstring &b, int p ) /* Callers like to pass us pointers into ourselves, so be careful! I don't know if we can use operator= with a pointer to our interior, so use an intermediate. */ size_t l = b.size(); data->command_line = b; - - data->check_size(); + data->command_line_changed(); if( p>=0 ) { @@ -2284,7 +2298,7 @@ void reader_push( const wchar_t *name ) data=n; - data->check_size(); + data->command_line_changed(); if( data->next == 0 ) { @@ -2351,45 +2365,43 @@ void reader_set_test_function( int (*f)( const wchar_t * ) ) /** A class as the context pointer for a background (threaded) highlight operation. */ class background_highlight_context_t { public: - /** - The string to highlight - */ + /** The string to highlight */ const wcstring string_to_highlight; /** Color buffer */ std::vector colors; - /** - The position to use for bracket matching - */ + /** The position to use for bracket matching */ const int match_highlight_pos; - /** - Function for syntax highlighting - */ + /** Function for syntax highlighting */ const highlight_function_t highlight_function; - /** - Environment variables - */ + /** Environment variables */ const env_vars vars; - /** - When the request was made - */ + /** When the request was made */ const double when; + /** Gen count at the time the request was made */ + const unsigned int generation_count; + background_highlight_context_t(const wcstring &pbuff, int phighlight_pos, highlight_function_t phighlight_func) : string_to_highlight(pbuff), match_highlight_pos(phighlight_pos), highlight_function(phighlight_func), vars(env_vars::highlighting_keys), - when(timef()) + when(timef()), + generation_count(s_generation_count) { colors.resize(string_to_highlight.size(), 0); } int threaded_highlight() { + if (generation_count != s_generation_count) { + // The gen count has changed, so don't do anything + return 0; + } const wchar_t *delayer = vars.get(L"HIGHLIGHT_DELAY"); double secDelay = 0; if (delayer) { @@ -2596,7 +2608,7 @@ static int read_i() data->buff_pos=0; data->command_line.clear(); - data->check_size(); + data->command_line_changed(); reader_run_command( parser, tmp ); free( (void *)tmp ); if( data->end_loop) @@ -2671,7 +2683,6 @@ const wchar_t *reader_readline() int finished=0; struct termios old_modes; - data->check_size(); data->search_buff.clear(); data->search_mode = NO_SEARCH; @@ -3199,7 +3210,7 @@ const wchar_t *reader_readline() /* Accept the autosuggestion */ data->command_line = data->autosuggestion; data->buff_pos = data->command_line.size(); - data->check_size(); + data->command_line_changed(); reader_super_highlight_me_plenty(data->buff_pos); reader_repaint(); }