diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-06-17 12:27:08 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-06-18 11:36:07 -0300 |
commit | 0621a6eaa51c8fc7a925b2578f8775b8ddd3d837 (patch) | |
tree | e977d66f165f512caf9447cf2b7a764da5224014 /src/nvim/os/event.c | |
parent | 05bf7808e0fcd66a4fd3e4b2b1cd124e43534bee (diff) | |
download | rneovim-0621a6eaa51c8fc7a925b2578f8775b8ddd3d837.tar.gz rneovim-0621a6eaa51c8fc7a925b2578f8775b8ddd3d837.tar.bz2 rneovim-0621a6eaa51c8fc7a925b2578f8775b8ddd3d837.zip |
events: Refactor how events are queued for processing
To make it possible reuse `event_poll` recursively and in other blocking
function calls, this changes how deferred/immediate events are processed:
- There are two queues in event.c, one for immediate events and another for
deferred events. The queue used when pushing/processing events is determined
with boolean arguments passed to `event_push`/`event_process` respectively.
- Events pushed to the immediate queue are processed inside `event_poll` but
after the `uv_run` call. This is required because libuv event loop does not
support recursion, and processing events may result in other `event_poll`
calls.
- Events pushed to the deferred queue are processed later by calling
`event_process(true)`. This is required to "trick" vim into treating all
asynchronous events as special keypresses, which is the least obtrusive
way of introducing asynchronicity into the editor.
- RStream instances will now forward the `defer` flag to the `event_push` call.
Diffstat (limited to 'src/nvim/os/event.c')
-rw-r--r-- | src/nvim/os/event.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/src/nvim/os/event.c b/src/nvim/os/event.c index 40ddf7097e..6723b97e0c 100644 --- a/src/nvim/os/event.c +++ b/src/nvim/os/event.c @@ -30,12 +30,13 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/event.c.generated.h" #endif -static klist_t(Event) *event_queue; +static klist_t(Event) *deferred_events, *immediate_events; void event_init() { - // Initialize the event queue - event_queue = kl_init(Event); + // Initialize the event queues + deferred_events = kl_init(Event); + immediate_events = kl_init(Event); // Initialize input events input_init(); // Timer to wake the event loop if a timeout argument is passed to @@ -67,7 +68,12 @@ bool event_poll(int32_t ms) return true; } - input_start(); + static int recursive = 0; + + if (!(recursive++)) { + // Only needs to start the libuv handle the first time we enter here + input_start(); + } uv_timer_t timer; uv_prepare_t timer_prepare; @@ -93,14 +99,21 @@ bool event_poll(int32_t ms) // Run one event loop iteration, blocking for events if run_mode is // UV_RUN_ONCE uv_run(uv_default_loop(), run_mode); + // Process immediate events outside uv_run since libuv event loop not + // support recursion(processing events may cause a recursive event_poll + // call) + event_process(false); } while ( // Continue running if ... !input_ready() && // we have no input - kl_empty(event_queue) && // no events are waiting to be processed + !event_has_deferred() && // no events are waiting to be processed run_mode != UV_RUN_NOWAIT && // ms != 0 !timer_data.timed_out); // we didn't get a timeout - input_stop(); + 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 @@ -111,26 +124,26 @@ bool event_poll(int32_t ms) event_process(false); } - return input_ready() || event_is_pending(); + return input_ready() || event_has_deferred(); } -bool event_is_pending() +bool event_has_deferred() { - return !kl_empty(event_queue); + return !kl_empty(get_queue(true)); } // Push an event to the queue -void event_push(Event event) +void event_push(Event event, bool deferred) { - *kl_pushp(Event, event_queue) = event; + *kl_pushp(Event, get_queue(deferred)) = event; } // Runs the appropriate action for each queued event -void event_process() +void event_process(bool deferred) { Event event; - while (kl_shift(Event, event_queue, &event) == 0) { + while (kl_shift(Event, get_queue(deferred), &event) == 0) { switch (event.type) { case kEventSignal: signal_handle(event); @@ -161,3 +174,8 @@ static void timer_prepare_cb(uv_prepare_t *handle) uv_timer_start(data->timer, timer_cb, (uint32_t)data->ms, 0); uv_prepare_stop(handle); } + +static klist_t(Event) *get_queue(bool deferred) +{ + return deferred ? deferred_events : immediate_events; +} |