aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/event
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2015-09-07 07:47:17 -0300
committerThiago de Arruda <tpadilha84@gmail.com>2015-09-07 07:47:17 -0300
commitbb46cc2c9ce9a36f19df5c29a403c1feb4dbdf88 (patch)
tree499d8bcf29973994fbcbdc0b19bd9eb0a67ce726 /src/nvim/event
parentf39ac698241885137e77efa4edeee7be21dd8deb (diff)
parenteb001a4abd2fbc740547c127807b2fc8367cc187 (diff)
downloadrneovim-bb46cc2c9ce9a36f19df5c29a403c1feb4dbdf88.tar.gz
rneovim-bb46cc2c9ce9a36f19df5c29a403c1feb4dbdf88.tar.bz2
rneovim-bb46cc2c9ce9a36f19df5c29a403c1feb4dbdf88.zip
Merge PR #3246 'Run builtin TUI in a another thread'
Diffstat (limited to 'src/nvim/event')
-rw-r--r--src/nvim/event/defs.h3
-rw-r--r--src/nvim/event/loop.c42
-rw-r--r--src/nvim/event/loop.h5
-rw-r--r--src/nvim/event/queue.c38
4 files changed, 58 insertions, 30 deletions
diff --git a/src/nvim/event/defs.h b/src/nvim/event/defs.h
index 5126d52241..b802866a3d 100644
--- a/src/nvim/event/defs.h
+++ b/src/nvim/event/defs.h
@@ -4,7 +4,7 @@
#include <assert.h>
#include <stdarg.h>
-#define EVENT_HANDLER_MAX_ARGC 4
+#define EVENT_HANDLER_MAX_ARGC 6
typedef void (*argv_callback)(void **argv);
typedef struct message {
@@ -12,6 +12,7 @@ typedef struct message {
argv_callback handler;
void *argv[EVENT_HANDLER_MAX_ARGC];
} Event;
+typedef void(*event_scheduler)(Event event, void *data);
#define VA_EVENT_INIT(event, p, h, a) \
do { \
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)
{
}
+
diff --git a/src/nvim/event/loop.h b/src/nvim/event/loop.h
index 9212a45aa4..0c1fcb5ed9 100644
--- a/src/nvim/event/loop.h
+++ b/src/nvim/event/loop.h
@@ -16,11 +16,14 @@ KLIST_INIT(WatcherPtr, WatcherPtr, _noop)
typedef struct loop {
uv_loop_t uv;
- Queue *events, *fast_events;
+ Queue *events, *fast_events, *thread_events;
klist_t(WatcherPtr) *children;
uv_signal_t children_watcher;
uv_timer_t children_kill_timer, poll_timer;
size_t children_stop_requests;
+ uv_async_t async;
+ uv_mutex_t mutex;
+ int recursive;
} Loop;
#define CREATE_EVENT(queue, handler, argc, ...) \
diff --git a/src/nvim/event/queue.c b/src/nvim/event/queue.c
index 19eca14144..c5ef22d426 100644
--- a/src/nvim/event/queue.c
+++ b/src/nvim/event/queue.c
@@ -105,16 +105,15 @@ static Queue *queue_new(Queue *parent, put_callback put_cb, void *data)
void queue_free(Queue *queue)
{
assert(queue);
- if (queue->parent) {
- while (!QUEUE_EMPTY(&queue->headtail)) {
- QUEUE *q = QUEUE_HEAD(&queue->headtail);
- QueueItem *item = queue_node_data(q);
- assert(!item->link);
+ while (!QUEUE_EMPTY(&queue->headtail)) {
+ QUEUE *q = QUEUE_HEAD(&queue->headtail);
+ QueueItem *item = queue_node_data(q);
+ if (queue->parent) {
QUEUE_REMOVE(&item->data.item.parent->node);
xfree(item->data.item.parent);
- QUEUE_REMOVE(q);
- xfree(item);
}
+ QUEUE_REMOVE(q);
+ xfree(item);
}
xfree(queue);
@@ -128,9 +127,8 @@ Event queue_get(Queue *queue)
void queue_put_event(Queue *queue, Event event)
{
assert(queue);
- assert(queue->parent); // don't push directly to the parent queue
queue_push(queue, event);
- if (queue->parent->put_cb) {
+ if (queue->parent && queue->parent->put_cb) {
queue->parent->put_cb(queue->parent, queue->parent->data);
}
}
@@ -177,11 +175,11 @@ static Event queue_remove(Queue *queue)
rv = child->data.item.event;
xfree(child);
} else {
- assert(queue->parent);
- assert(!queue_empty(queue->parent));
- // remove the corresponding link node in the parent queue
- QUEUE_REMOVE(&item->data.item.parent->node);
- xfree(item->data.item.parent);
+ if (queue->parent) {
+ // remove the corresponding link node in the parent queue
+ QUEUE_REMOVE(&item->data.item.parent->node);
+ xfree(item->data.item.parent);
+ }
rv = item->data.item.event;
}
@@ -195,11 +193,13 @@ static void queue_push(Queue *queue, Event event)
item->link = false;
item->data.item.event = event;
QUEUE_INSERT_TAIL(&queue->headtail, &item->node);
- // push link node to the parent queue
- item->data.item.parent = xmalloc(sizeof(QueueItem));
- item->data.item.parent->link = true;
- item->data.item.parent->data.queue = queue;
- QUEUE_INSERT_TAIL(&queue->parent->headtail, &item->data.item.parent->node);
+ if (queue->parent) {
+ // push link node to the parent queue
+ item->data.item.parent = xmalloc(sizeof(QueueItem));
+ item->data.item.parent->link = true;
+ item->data.item.parent->data.queue = queue;
+ QUEUE_INSERT_TAIL(&queue->parent->headtail, &item->data.item.parent->node);
+ }
}
static QueueItem *queue_node_data(QUEUE *q)