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)  {  } +  | 
