diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-11-02 16:37:08 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-11-02 16:47:50 -0300 |
commit | a1dd70b1d0e9ef155c81eeb249f137e763482d10 (patch) | |
tree | d80bf394168eb84f6eaf3630d091a40cf2b9e379 /src/nvim/os/event.c | |
parent | e378965a4483881c3f737eed5c3d24cb1f305a62 (diff) | |
download | rneovim-a1dd70b1d0e9ef155c81eeb249f137e763482d10.tar.gz rneovim-a1dd70b1d0e9ef155c81eeb249f137e763482d10.tar.bz2 rneovim-a1dd70b1d0e9ef155c81eeb249f137e763482d10.zip |
event: Reintroduce the immediate event queue
Commit @264e0d872c("Remove automatic event deferral") removed the immediate
event queue because event deferral now had to be explicit. The problem is that
while some events don't need to be deferred, they still can result in recursive
`event_poll` calls, and recursion is not supported by libuv. Examples of those
are msgpack-rpc requests while a server->client request is pending, or signals
which can call `mch_exit`(and that will result in `uv_run` calls).
To fix the problem, this reintroduces the immediate event queue for events that
can potentially result in event loop recursion. The non-deferred events are
still processed in `event_poll`, but only after `uv_run` returns.
Diffstat (limited to 'src/nvim/os/event.c')
-rw-r--r-- | src/nvim/os/event.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/src/nvim/os/event.c b/src/nvim/os/event.c index 657f1edad0..e09303e505 100644 --- a/src/nvim/os/event.c +++ b/src/nvim/os/event.c @@ -35,18 +35,24 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/event.c.generated.h" #endif -static klist_t(Event) *deferred_events; +// deferred_events: Events that should be processed as the K_EVENT special key +// immediate_events: Events that should be processed after exiting libuv event +// loop(to avoid recursion), but before returning from +// `event_poll` +static klist_t(Event) *deferred_events, *immediate_events; void event_init(void) { // Initialize the event queues deferred_events = kl_init(Event); + immediate_events = kl_init(Event); // early msgpack-rpc initialization msgpack_rpc_init_method_table(); msgpack_rpc_helpers_init(); wstream_init(); // Initialize input events input_init(); + input_start(); // Timer to wake the event loop if a timeout argument is passed to // `event_poll` // Signals @@ -65,20 +71,19 @@ void event_teardown(void) channel_teardown(); job_teardown(); server_teardown(); + input_stop(); } // Wait for some event void event_poll(int ms) { - uv_run_mode run_mode = UV_RUN_ONCE; - static int recursive = 0; - if (!(recursive++)) { - // Only needs to start the libuv handle the first time we enter here - input_start(); + if (recursive++) { + abort(); // Should not re-enter uv_run } + uv_run_mode run_mode = UV_RUN_ONCE; uv_timer_t timer; uv_prepare_t timer_prepare; TimerData timer_data = {.ms = ms, .timed_out = false, .timer = &timer}; @@ -101,18 +106,18 @@ void event_poll(int ms) loop(run_mode); - if (!(--recursive)) { - // Again, only stop when we leave the top-level invocation - input_stop(); - } - if (ms > 0) { // Ensure the timer-related handles are closed and run the event loop // once more to let libuv perform it's cleanup + uv_timer_stop(&timer); + uv_prepare_stop(&timer_prepare); uv_close((uv_handle_t *)&timer, NULL); uv_close((uv_handle_t *)&timer_prepare, NULL); loop(UV_RUN_NOWAIT); } + + recursive--; // Can re-enter uv_run now + process_events_from(immediate_events); } bool event_has_deferred(void) @@ -121,17 +126,21 @@ bool event_has_deferred(void) } // Queue an event -void event_push(Event event) +void event_push(Event event, bool deferred) { - *kl_pushp(Event, deferred_events) = event; + *kl_pushp(Event, deferred ? deferred_events : immediate_events) = event; } - void event_process(void) { + process_events_from(deferred_events); +} + +static void process_events_from(klist_t(Event) *queue) +{ Event event; - while (kl_shift(Event, deferred_events, &event) == 0) { + while (kl_shift(Event, queue, &event) == 0) { event.handler(event); } } |