diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/ui.c | 4 | ||||
-rw-r--r-- | src/nvim/event/loop.c | 3 | ||||
-rw-r--r-- | src/nvim/tui/tui.c | 21 | ||||
-rw-r--r-- | src/nvim/ui.c | 10 | ||||
-rw-r--r-- | src/nvim/ui_bridge.c | 3 |
5 files changed, 26 insertions, 15 deletions
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 35508fde6b..760c95eb5b 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -43,10 +43,10 @@ void remote_ui_disconnect(uint64_t channel_id) return; } UIData *data = ui->data; - // destroy pending screen updates - api_free_array(data->buffer); + api_free_array(data->buffer); // Destroy pending screen updates. pmap_del(uint64_t)(connected_uis, channel_id); xfree(ui->data); + ui->data = NULL; // Flag UI as "stopped". ui_detach_impl(ui); xfree(ui); } diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 55ef0261d9..d92464f17b 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -33,6 +33,9 @@ void loop_init(Loop *loop, void *data) loop->poll_timer.data = xmalloc(sizeof(bool)); // "timeout expired" flag } +/// Processes one `Loop.uv` event (at most). +/// Processes all `Loop.fast_events` events. +/// /// @returns true if `ms` timeout was reached bool loop_poll_events(Loop *loop, int ms) { diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index f3383eb006..2dfe7faa04 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -69,7 +69,6 @@ typedef struct { typedef struct { UIBridgeData *bridge; Loop *loop; - bool stop; unibi_var_t params[9]; char buf[OUTBUF_SIZE]; size_t bufpos; @@ -124,7 +123,7 @@ static bool cursor_style_enabled = false; UI *tui_start(void) { - UI *ui = xcalloc(1, sizeof(UI)); + UI *ui = xcalloc(1, sizeof(UI)); // Freed by ui_bridge_stop(). ui->stop = tui_stop; ui->rgb = p_tgc; ui->resize = tui_resize; @@ -324,11 +323,11 @@ static void tui_terminal_stop(UI *ui) static void tui_stop(UI *ui) { tui_terminal_stop(ui); - TUIData *data = ui->data; - data->stop = true; + // Flag UI as "stopped". Needed by tui_scheduler (called from main thread). + ui->data = NULL; } -// Main function of the TUI thread +/// Main function of the TUI thread. static void tui_main(UIBridgeData *bridge, UI *ui) { Loop tui_loop; @@ -349,7 +348,6 @@ static void tui_main(UIBridgeData *bridge, UI *ui) #endif term_input_init(&data->input, &tui_loop); tui_terminal_start(ui); - data->stop = false; // Allow main thread to continue, we are ready to handle UI callbacks. CONTINUE(bridge); @@ -358,17 +356,17 @@ static void tui_main(UIBridgeData *bridge, UI *ui) event_create(show_termcap_event, 1, data->ut)); // "Active" loop: first ~100 ms of startup. - for (size_t ms = 0; ms < 100 && !data->stop;) { + for (size_t ms = 0; ms < 100 && !ui_is_stopped(ui);) { ms += (loop_poll_events(&tui_loop, 20) ? 20 : 1); } - if (!data->stop) { + if (!ui_is_stopped(ui)) { tui_terminal_after_startup(ui); // Tickle `main_loop` with a dummy event, else the initial "focus-gained" // terminal response may not get processed until user hits a key. loop_schedule_deferred(&main_loop, event_create(tui_dummy_event, 0)); } // "Passive" (I/O-driven) loop: TUI thread "main loop". - while (!data->stop) { + while (!ui_is_stopped(ui)) { loop_poll_events(&tui_loop, -1); // tui_loop.events is never processed } @@ -380,16 +378,19 @@ static void tui_main(UIBridgeData *bridge, UI *ui) loop_close(&tui_loop, false); kv_destroy(data->invalid_regions); xfree(data); - xfree(ui); } static void tui_dummy_event(void **argv) { } +/// Handoff point between the main (ui_bridge) thread and the TUI thread. static void tui_scheduler(Event event, void *d) { UI *ui = d; + if (ui_is_stopped(ui)) { + return; // tui_stop was handled, teardown underway. + } TUIData *data = ui->data; loop_schedule(data->loop, event); // `tui_loop` local to tui_main(). } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 81da88c54a..8aec923538 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -143,6 +143,12 @@ void ui_builtin_stop(void) UI_CALL(stop); } +/// Returns true if UI `ui` is stopped. +bool ui_is_stopped(UI *ui) +{ + return ui->data == NULL; +} + bool ui_rgb_attached(void) { for (size_t i = 0; i < ui_count; i++) { @@ -404,7 +410,7 @@ void ui_start_highlight(int attr_code) { current_attr_code = attr_code; - if (!ui_count) { + if (!ui_active()) { return; } @@ -415,7 +421,7 @@ void ui_stop_highlight(void) { current_attr_code = HL_NORMAL; - if (!ui_count) { + if (!ui_active()) { return; } diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c index 0a69cf0ecb..16dd42ebaa 100644 --- a/src/nvim/ui_bridge.c +++ b/src/nvim/ui_bridge.c @@ -118,11 +118,12 @@ static void ui_bridge_stop(UI *b) if (stopped) { break; } - loop_poll_events(&main_loop, 10); + loop_poll_events(&main_loop, 10); // Process one event. } uv_thread_join(&bridge->ui_thread); uv_mutex_destroy(&bridge->mutex); uv_cond_destroy(&bridge->cond); + xfree(bridge->ui); // Threads joined, now safe to free UI container. #7922 ui_detach_impl(b); xfree(b); } |