mirror of
https://github.com/neovim/neovim.git
synced 2026-08-31 03:13:48 +00:00
event: Refactor async event processing
- Improve the implementation of deferred/immediate events. - Use the new queue module to change how/when events are queued/processed by giving a private queue to each emitter. - Immediate events(which only exist to break uv_run recursion) are now represented in the `loop->fast_events` queue. - Events pushed to child queues are propagated to the event loop main queue and processed as K_EVENT keys.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <uv.h>
|
||||
@@ -9,15 +10,20 @@
|
||||
# include "event/loop.c.generated.h"
|
||||
#endif
|
||||
|
||||
typedef struct idle_event {
|
||||
uv_idle_t idle;
|
||||
Event event;
|
||||
} IdleEvent;
|
||||
|
||||
|
||||
void loop_init(Loop *loop, void *data)
|
||||
{
|
||||
uv_loop_init(&loop->uv);
|
||||
loop->uv.data = loop;
|
||||
loop->deferred_events = kl_init(Event);
|
||||
loop->immediate_events = kl_init(Event);
|
||||
loop->children = kl_init(WatcherPtr);
|
||||
loop->children_stop_requests = 0;
|
||||
loop->events = queue_new_parent(on_put, loop);
|
||||
loop->fast_events = queue_new_child(loop->events);
|
||||
uv_signal_init(&loop->uv, &loop->children_watcher);
|
||||
uv_timer_init(&loop->uv, &loop->children_kill_timer);
|
||||
uv_timer_init(&loop->uv, &loop->poll_timer);
|
||||
@@ -50,29 +56,20 @@ void loop_poll_events(Loop *loop, int ms)
|
||||
}
|
||||
|
||||
recursive--; // Can re-enter uv_run now
|
||||
process_events_from(loop->immediate_events);
|
||||
queue_process_events(loop->fast_events);
|
||||
}
|
||||
|
||||
|
||||
// Queue an event
|
||||
void loop_push_event(Loop *loop, Event event, bool deferred)
|
||||
static void on_put(Queue *queue, void *data)
|
||||
{
|
||||
Loop *loop = data;
|
||||
// Sometimes libuv will run pending callbacks(timer for example) before
|
||||
// blocking for a poll. If this happens and the callback pushes a event to one
|
||||
// of the queues, the event would only be processed after the poll
|
||||
// returns(user hits a key for example). To avoid this scenario, we call
|
||||
// uv_stop when a event is enqueued.
|
||||
uv_stop(&loop->uv);
|
||||
kl_push(Event, deferred ? loop->deferred_events : loop->immediate_events,
|
||||
event);
|
||||
}
|
||||
|
||||
void loop_process_event(Loop *loop)
|
||||
{
|
||||
process_events_from(loop->deferred_events);
|
||||
}
|
||||
|
||||
|
||||
void loop_close(Loop *loop)
|
||||
{
|
||||
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
|
||||
@@ -83,20 +80,6 @@ void loop_close(Loop *loop)
|
||||
} while (uv_loop_close(&loop->uv));
|
||||
}
|
||||
|
||||
void loop_process_all_events(Loop *loop)
|
||||
{
|
||||
process_events_from(loop->immediate_events);
|
||||
process_events_from(loop->deferred_events);
|
||||
}
|
||||
|
||||
static void process_events_from(klist_t(Event) *queue)
|
||||
{
|
||||
while (!kl_empty(queue)) {
|
||||
Event event = kl_shift(Event, queue);
|
||||
event.handler(event);
|
||||
}
|
||||
}
|
||||
|
||||
static void timer_cb(uv_timer_t *handle)
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user