diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2015-09-01 10:11:55 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2015-09-06 09:18:53 -0300 |
commit | c20b802511a3d0e3b2277186a545c7f9f687410c (patch) | |
tree | 7118c3a32883bd831f234d1d1df205871e0fba97 /src/nvim/event/loop.c | |
parent | 203a4d5650ced506ae82ed6c79bd056a547f28c6 (diff) | |
download | rneovim-c20b802511a3d0e3b2277186a545c7f9f687410c.tar.gz rneovim-c20b802511a3d0e3b2277186a545c7f9f687410c.tar.bz2 rneovim-c20b802511a3d0e3b2277186a545c7f9f687410c.zip |
loop: Improvements for thread-safety
- Implement `loop_schedule` method for queueing events from other threads
- Make `loop_poll_events` `recursive` static variable a field of the Loop
structure
Diffstat (limited to 'src/nvim/event/loop.c')
-rw-r--r-- | src/nvim/event/loop.c | 42 |
1 files changed, 33 insertions, 9 deletions
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c index 3d3288f858..088e059d19 100644 --- a/src/nvim/event/loop.c +++ b/src/nvim/event/loop.c @@ -10,20 +10,19 @@ # 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->recursive = 0; loop->uv.data = loop; loop->children = kl_init(WatcherPtr); loop->children_stop_requests = 0; loop->events = queue_new_parent(loop_on_put, loop); loop->fast_events = queue_new_child(loop->events); + loop->thread_events = queue_new_parent(NULL, NULL); + uv_mutex_init(&loop->mutex); + uv_async_init(&loop->uv, &loop->async, async_cb); 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); @@ -31,9 +30,7 @@ void loop_init(Loop *loop, void *data) void loop_poll_events(Loop *loop, int ms) { - static int recursive = 0; - - if (recursive++) { + if (loop->recursive++) { abort(); // Should not re-enter uv_run } @@ -55,10 +52,19 @@ void loop_poll_events(Loop *loop, int ms) uv_timer_stop(&loop->poll_timer); } - recursive--; // Can re-enter uv_run now + loop->recursive--; // Can re-enter uv_run now queue_process_events(loop->fast_events); } +// Schedule an event from another thread +void loop_schedule(Loop *loop, Event event) +{ + uv_mutex_lock(&loop->mutex); + queue_put_event(loop->thread_events, event); + uv_async_send(&loop->async); + uv_mutex_unlock(&loop->mutex); +} + void loop_on_put(Queue *queue, void *data) { Loop *loop = data; @@ -72,14 +78,32 @@ void loop_on_put(Queue *queue, void *data) void loop_close(Loop *loop) { + uv_mutex_destroy(&loop->mutex); uv_close((uv_handle_t *)&loop->children_watcher, NULL); uv_close((uv_handle_t *)&loop->children_kill_timer, NULL); uv_close((uv_handle_t *)&loop->poll_timer, NULL); + uv_close((uv_handle_t *)&loop->async, NULL); do { uv_run(&loop->uv, UV_RUN_DEFAULT); } while (uv_loop_close(&loop->uv)); + queue_free(loop->events); + queue_free(loop->fast_events); + queue_free(loop->thread_events); + kl_destroy(WatcherPtr, loop->children); +} + +static void async_cb(uv_async_t *handle) +{ + Loop *l = handle->loop->data; + uv_mutex_lock(&l->mutex); + while (!queue_empty(l->thread_events)) { + Event ev = queue_get(l->thread_events); + queue_put_event(l->fast_events, ev); + } + uv_mutex_unlock(&l->mutex); } static void timer_cb(uv_timer_t *handle) { } + |