aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago de Arruda <tpadilha84@gmail.com>2015-07-16 23:10:04 -0300
committerThiago de Arruda <tpadilha84@gmail.com>2015-07-17 00:19:19 -0300
commit991d3ec1e679bb6407f2a5820910d2968424183c (patch)
tree38810fb657e1e1ea9d77b7a7963e874e8bda99d1
parent9e42ef4e1312fb6888d2691e9d979b95dd43ec94 (diff)
downloadrneovim-991d3ec1e679bb6407f2a5820910d2968424183c.tar.gz
rneovim-991d3ec1e679bb6407f2a5820910d2968424183c.tar.bz2
rneovim-991d3ec1e679bb6407f2a5820910d2968424183c.zip
event loop: New abstraction layer with refactored time/signal API
- Add event loop abstraction module under src/nvim/event. The src/nvim/event/loop module replaces src/nvim/os/event - Remove direct dependency on libuv signal/timer API and use the new abstraction instead. - Replace all references to uv_default_loop() by &loop.uv, a new global variable that wraps libuv main event loop but allows the event loop functions to be reused in other contexts.
-rw-r--r--src/nvim/CMakeLists.txt4
-rw-r--r--src/nvim/edit.c8
-rw-r--r--src/nvim/eval.c8
-rw-r--r--src/nvim/event/loop.c137
-rw-r--r--src/nvim/event/loop.h (renamed from src/nvim/os/event.h)38
-rw-r--r--src/nvim/event/signal.c52
-rw-r--r--src/nvim/event/signal.h22
-rw-r--r--src/nvim/event/time.c55
-rw-r--r--src/nvim/event/time.h20
-rw-r--r--src/nvim/ex_getln.c8
-rw-r--r--src/nvim/getchar.c2
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/main.c42
-rw-r--r--src/nvim/msgpack_rpc/channel.c9
-rw-r--r--src/nvim/msgpack_rpc/server.c8
-rw-r--r--src/nvim/normal.c8
-rw-r--r--src/nvim/os/event.c177
-rw-r--r--src/nvim/os/event_defs.h17
-rw-r--r--src/nvim/os/input.c10
-rw-r--r--src/nvim/os/job.c40
-rw-r--r--src/nvim/os/job.h2
-rw-r--r--src/nvim/os/job_private.h5
-rw-r--r--src/nvim/os/pipe_process.c10
-rw-r--r--src/nvim/os/pty_process.c8
-rw-r--r--src/nvim/os/rstream.c6
-rw-r--r--src/nvim/os/rstream.h1
-rw-r--r--src/nvim/os/shell.c2
-rw-r--r--src/nvim/os/signal.c51
-rw-r--r--src/nvim/os/signal.h2
-rw-r--r--src/nvim/os/time.c4
-rw-r--r--src/nvim/os/wstream.c2
-rw-r--r--src/nvim/os_unix.c2
-rw-r--r--src/nvim/terminal.c23
-rw-r--r--src/nvim/tui/term_input.inl24
-rw-r--r--src/nvim/tui/tui.c20
-rw-r--r--src/nvim/ui.c4
-rw-r--r--test/unit/os/fs_spec.lua2
-rw-r--r--test/unit/os/shell_spec.lua2
38 files changed, 499 insertions, 338 deletions
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index ad5bac1898..4448859b64 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -30,15 +30,17 @@ file(MAKE_DIRECTORY ${GENERATED_DIR}/api)
file(MAKE_DIRECTORY ${GENERATED_DIR}/api/private)
file(MAKE_DIRECTORY ${GENERATED_DIR}/msgpack_rpc)
file(MAKE_DIRECTORY ${GENERATED_DIR}/tui)
+file(MAKE_DIRECTORY ${GENERATED_DIR}/event)
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR})
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/os)
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api)
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api/private)
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/msgpack_rpc)
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/tui)
+file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/event)
file(GLOB NEOVIM_SOURCES *.c os/*.c api/*.c api/private/*.c msgpack_rpc/*.c
- tui/*.c)
+ tui/*.c event/*.c)
file(GLOB_RECURSE NEOVIM_HEADERS *.h)
file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index dd82b06158..390d62210b 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -59,7 +59,7 @@
#include "nvim/terminal.h"
#include "nvim/undo.h"
#include "nvim/window.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/input.h"
#include "nvim/os/time.h"
@@ -601,15 +601,15 @@ edit (
* Get a character for Insert mode. Ignore K_IGNORE.
*/
lastc = c; /* remember previous char for CTRL-D */
- event_enable_deferred();
+ loop_enable_deferred_events(&loop);
do {
c = safe_vgetc();
} while (c == K_IGNORE);
- event_disable_deferred();
+ loop_disable_deferred_events(&loop);
if (c == K_EVENT) {
c = lastc;
- event_process();
+ loop_process_event(&loop);
continue;
}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 7da5cfb731..4173acefd9 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -91,8 +91,8 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/os/dl.h"
-#include "nvim/os/event.h"
#include "nvim/os/input.h"
+#include "nvim/event/loop.h"
#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */
@@ -10966,7 +10966,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
if (!disable_job_defer++) {
// process any pending job events in the deferred queue, but only do this if
// deferred is not disabled(at the top-level `jobwait()` call)
- event_process();
+ loop_process_event(&loop);
}
// For each item in the input list append an integer to the output list. -3
// is used to represent an invalid job id, -2 is for a interrupted job and
@@ -11026,7 +11026,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
}
// poll to ensure any pending callbacks from the last job are invoked
- event_poll(0);
+ loop_poll_events(&loop, 0);
for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) {
Job *job = NULL;
@@ -20347,7 +20347,7 @@ static inline void push_job_event(Job *job, ufunc_T *callback,
event_data->data = job_data(job);
event_data->callback = callback;
event_data->type = type;
- event_push((Event) {
+ loop_push_event(&loop, (Event) {
.handler = on_job_event,
.data = event_data
}, !disable_job_defer);
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c
new file mode 100644
index 0000000000..c467ae8b96
--- /dev/null
+++ b/src/nvim/event/loop.c
@@ -0,0 +1,137 @@
+#include <stdint.h>
+
+#include <uv.h>
+
+#include "nvim/event/loop.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "event/loop.c.generated.h"
+#endif
+
+
+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);
+}
+
+void loop_poll_events(Loop *loop, int ms)
+{
+ static int recursive = 0;
+
+ if (recursive++) {
+ abort(); // Should not re-enter uv_run
+ }
+
+ bool wait = true;
+ uv_timer_t timer;
+
+ if (ms > 0) {
+ uv_timer_init(&loop->uv, &timer);
+ // Use a repeating timeout of ms milliseconds to make sure
+ // we do not block indefinitely for I/O.
+ uv_timer_start(&timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
+ } else if (ms == 0) {
+ // For ms == 0, we need to do a non-blocking event poll by
+ // setting the run mode to UV_RUN_NOWAIT.
+ wait = false;
+ }
+
+ if (wait) {
+ loop_run_once(loop);
+ } else {
+ loop_run_nowait(loop);
+ }
+
+ if (ms > 0) {
+ // Ensure the timer handle is closed and run the event loop
+ // once more to let libuv perform it's cleanup
+ uv_timer_stop(&timer);
+ uv_close((uv_handle_t *)&timer, NULL);
+ loop_run_nowait(loop);
+ }
+
+ recursive--; // Can re-enter uv_run now
+ process_events_from(loop->immediate_events);
+}
+
+bool loop_has_deferred_events(Loop *loop)
+{
+ return loop->deferred_events_allowed && !kl_empty(loop->deferred_events);
+}
+
+void loop_enable_deferred_events(Loop *loop)
+{
+ ++loop->deferred_events_allowed;
+}
+
+void loop_disable_deferred_events(Loop *loop)
+{
+ --loop->deferred_events_allowed;
+}
+
+// Queue an event
+void loop_push_event(Loop *loop, Event event, bool deferred)
+{
+ // 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.
+ loop_stop(loop);
+ 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_run(Loop *loop)
+{
+ uv_run(&loop->uv, UV_RUN_DEFAULT);
+}
+
+void loop_run_once(Loop *loop)
+{
+ uv_run(&loop->uv, UV_RUN_ONCE);
+}
+
+void loop_run_nowait(Loop *loop)
+{
+ uv_run(&loop->uv, UV_RUN_NOWAIT);
+}
+
+void loop_stop(Loop *loop)
+{
+ uv_stop(&loop->uv);
+}
+
+void loop_close(Loop *loop)
+{
+ do {
+ uv_run(&loop->uv, UV_RUN_DEFAULT);
+ } 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)
+{
+}
diff --git a/src/nvim/os/event.h b/src/nvim/event/loop.h
index db02b38c7f..e5a890dddb 100644
--- a/src/nvim/os/event.h
+++ b/src/nvim/event/loop.h
@@ -1,20 +1,40 @@
-#ifndef NVIM_OS_EVENT_H
-#define NVIM_OS_EVENT_H
+#ifndef NVIM_EVENT_LOOP_H
+#define NVIM_EVENT_LOOP_H
#include <stdint.h>
-#include <stdbool.h>
-#include "nvim/os/event_defs.h"
-#include "nvim/os/job_defs.h"
+#include <uv.h>
+
+#include "nvim/lib/klist.h"
#include "nvim/os/time.h"
+typedef struct event Event;
+typedef void (*event_handler)(Event event);
+
+struct event {
+ void *data;
+ event_handler handler;
+};
+
+typedef void * WatcherPtr;
+
+#define _noop(x)
+KLIST_INIT(WatcherPtr, WatcherPtr, _noop)
+KLIST_INIT(Event, Event, _noop)
+
+typedef struct loop {
+ uv_loop_t uv;
+ klist_t(Event) *deferred_events, *immediate_events;
+ int deferred_events_allowed;
+} Loop;
+
// Poll for events until a condition or timeout
-#define event_poll_until(timeout, condition) \
+#define LOOP_POLL_EVENTS_UNTIL(loop, timeout, condition) \
do { \
int remaining = timeout; \
uint64_t before = (remaining > 0) ? os_hrtime() : 0; \
while (!(condition)) { \
- event_poll(remaining); \
+ loop_poll_events(loop, remaining); \
if (remaining == 0) { \
break; \
} else if (remaining > 0) { \
@@ -29,7 +49,7 @@
} while (0)
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "os/event.h.generated.h"
+# include "event/loop.h.generated.h"
#endif
-#endif // NVIM_OS_EVENT_H
+#endif // NVIM_EVENT_LOOP_H
diff --git a/src/nvim/event/signal.c b/src/nvim/event/signal.c
new file mode 100644
index 0000000000..63133b4f57
--- /dev/null
+++ b/src/nvim/event/signal.c
@@ -0,0 +1,52 @@
+#include <uv.h>
+
+#include "nvim/event/loop.h"
+#include "nvim/event/signal.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "event/signal.c.generated.h"
+#endif
+
+
+void signal_watcher_init(Loop *loop, SignalWatcher *watcher, void *data)
+ FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(2)
+{
+ uv_signal_init(&loop->uv, &watcher->uv);
+ watcher->uv.data = watcher;
+ watcher->data = data;
+ watcher->cb = NULL;
+}
+
+void signal_watcher_start(SignalWatcher *watcher, signal_cb cb, int signum)
+ FUNC_ATTR_NONNULL_ALL
+{
+ watcher->cb = cb;
+ uv_signal_start(&watcher->uv, signal_watcher_cb, signum);
+}
+
+void signal_watcher_stop(SignalWatcher *watcher)
+ FUNC_ATTR_NONNULL_ALL
+{
+ uv_signal_stop(&watcher->uv);
+}
+
+void signal_watcher_close(SignalWatcher *watcher, signal_close_cb cb)
+ FUNC_ATTR_NONNULL_ARG(1)
+{
+ watcher->close_cb = cb;
+ uv_close((uv_handle_t *)&watcher->uv, close_cb);
+}
+
+static void signal_watcher_cb(uv_signal_t *handle, int signum)
+{
+ SignalWatcher *watcher = handle->data;
+ watcher->cb(watcher, signum, watcher->data);
+}
+
+static void close_cb(uv_handle_t *handle)
+{
+ SignalWatcher *watcher = handle->data;
+ if (watcher->close_cb) {
+ watcher->close_cb(watcher, watcher->data);
+ }
+}
diff --git a/src/nvim/event/signal.h b/src/nvim/event/signal.h
new file mode 100644
index 0000000000..c269fa9d95
--- /dev/null
+++ b/src/nvim/event/signal.h
@@ -0,0 +1,22 @@
+#ifndef NVIM_EVENT_SIGNAL_H
+#define NVIM_EVENT_SIGNAL_H
+
+#include <uv.h>
+
+#include "nvim/event/loop.h"
+
+typedef struct signal_watcher SignalWatcher;
+typedef void (*signal_cb)(SignalWatcher *watcher, int signum, void *data);
+typedef void (*signal_close_cb)(SignalWatcher *watcher, void *data);
+
+struct signal_watcher {
+ uv_signal_t uv;
+ void *data;
+ signal_cb cb;
+ signal_close_cb close_cb;
+};
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "event/signal.h.generated.h"
+#endif
+#endif // NVIM_EVENT_SIGNAL_H
diff --git a/src/nvim/event/time.c b/src/nvim/event/time.c
new file mode 100644
index 0000000000..ce33cdfc10
--- /dev/null
+++ b/src/nvim/event/time.c
@@ -0,0 +1,55 @@
+#include <stdint.h>
+
+#include <uv.h>
+
+#include "nvim/event/loop.h"
+#include "nvim/event/time.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "event/time.c.generated.h"
+#endif
+
+
+void time_watcher_init(Loop *loop, TimeWatcher *watcher, void *data)
+ FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(2)
+{
+ uv_timer_init(&loop->uv, &watcher->uv);
+ watcher->uv.data = watcher;
+ watcher->data = data;
+}
+
+void time_watcher_start(TimeWatcher *watcher, time_cb cb, uint64_t timeout,
+ uint64_t repeat)
+ FUNC_ATTR_NONNULL_ALL
+{
+ watcher->cb = cb;
+ uv_timer_start(&watcher->uv, time_watcher_cb, timeout, repeat);
+}
+
+void time_watcher_stop(TimeWatcher *watcher)
+ FUNC_ATTR_NONNULL_ALL
+{
+ uv_timer_stop(&watcher->uv);
+}
+
+void time_watcher_close(TimeWatcher *watcher, time_cb cb)
+ FUNC_ATTR_NONNULL_ARG(1)
+{
+ watcher->close_cb = cb;
+ uv_close((uv_handle_t *)&watcher->uv, close_cb);
+}
+
+static void time_watcher_cb(uv_timer_t *handle)
+ FUNC_ATTR_NONNULL_ALL
+{
+ TimeWatcher *watcher = handle->data;
+ watcher->cb(watcher, watcher->data);
+}
+
+static void close_cb(uv_handle_t *handle)
+{
+ TimeWatcher *watcher = handle->data;
+ if (watcher->close_cb) {
+ watcher->close_cb(watcher, watcher->data);
+ }
+}
diff --git a/src/nvim/event/time.h b/src/nvim/event/time.h
new file mode 100644
index 0000000000..ee50e53d11
--- /dev/null
+++ b/src/nvim/event/time.h
@@ -0,0 +1,20 @@
+#ifndef NVIM_EVENT_TIME_H
+#define NVIM_EVENT_TIME_H
+
+#include <uv.h>
+
+#include "nvim/event/loop.h"
+
+typedef struct time_watcher TimeWatcher;
+typedef void (*time_cb)(TimeWatcher *watcher, void *data);
+
+struct time_watcher {
+ uv_timer_t uv;
+ void *data;
+ time_cb cb, close_cb;
+};
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "event/time.h.generated.h"
+#endif
+#endif // NVIM_EVENT_TIME_H
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 3af035a6e3..785db1dbd1 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -63,7 +63,7 @@
#include "nvim/window.h"
#include "nvim/ui.h"
#include "nvim/os/os.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
/*
* Variables shared between getcmdline(), redrawcmdline() and others.
@@ -298,14 +298,14 @@ getcmdline (
/* Get a character. Ignore K_IGNORE, it should not do anything, such
* as stop completion. */
- event_enable_deferred();
+ loop_enable_deferred_events(&loop);
do {
c = safe_vgetc();
} while (c == K_IGNORE);
- event_disable_deferred();
+ loop_disable_deferred_events(&loop);
if (c == K_EVENT) {
- event_process();
+ loop_process_event(&loop);
continue;
}
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 864aa6a622..bbeef376b0 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -49,7 +49,7 @@
#include "nvim/strings.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 1d93900a94..c7164ef1f1 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -28,6 +28,7 @@
#include "nvim/menu.h"
#include "nvim/syntax_defs.h"
#include "nvim/types.h"
+#include "nvim/event/loop.h"
/*
* definition of global variables
@@ -1216,6 +1217,7 @@ EXTERN char *ignoredp;
// If a msgpack-rpc channel should be started over stdin/stdout
EXTERN bool embedded_mode INIT(= false);
+EXTERN Loop loop;
/// Used to track the status of external functions.
/// Currently only used for iconv().
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 50c16c51d6..ca55469730 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -61,9 +61,13 @@
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/signal.h"
+#include "nvim/os/job.h"
+#include "nvim/msgpack_rpc/defs.h"
#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/msgpack_rpc/server.h"
+#include "nvim/msgpack_rpc/channel.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/handle.h"
@@ -133,6 +137,42 @@ static const char *err_extra_cmd =
N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments");
+void event_init(void)
+{
+ loop_init(&loop, NULL);
+ // early msgpack-rpc initialization
+ msgpack_rpc_init_method_table();
+ msgpack_rpc_helpers_init();
+ // Initialize input events
+ input_init();
+ // Timer to wake the event loop if a timeout argument is passed to
+ // `event_poll`
+ // Signals
+ signal_init();
+ job_init();
+ // finish mspgack-rpc initialization
+ channel_init();
+ server_init();
+ terminal_init();
+}
+
+void event_teardown(void)
+{
+ if (!loop.deferred_events) {
+ return;
+ }
+
+ loop_process_all_events(&loop);
+ input_stop();
+ channel_teardown();
+ job_teardown();
+ server_teardown();
+ signal_teardown();
+ terminal_teardown();
+
+ loop_close(&loop);
+}
+
/// Performs early initialization.
///
/// Needed for unit tests. Must be called after `time_init()`.
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 2a81b4f160..3932fa1f36 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -9,7 +9,7 @@
#include "nvim/api/vim.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/remote_ui.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/rstream.h"
#include "nvim/os/rstream_defs.h"
#include "nvim/os/wstream.h"
@@ -220,7 +220,7 @@ Object channel_send_call(uint64_t id,
ChannelCallFrame frame = {request_id, false, false, NIL};
kv_push(ChannelCallFrame *, channel->call_stack, &frame);
channel->pending_requests++;
- event_poll_until(-1, frame.returned);
+ LOOP_POLL_EVENTS_UNTIL(&loop, -1, frame.returned);
(void)kv_pop(channel->call_stack);
channel->pending_requests--;
@@ -474,7 +474,7 @@ static void handle_request(Channel *channel, msgpack_object *request)
event_data->args = args;
event_data->request_id = request_id;
incref(channel);
- event_push((Event) {
+ loop_push_event(&loop, (Event) {
.handler = on_request_event,
.data = event_data
}, defer);
@@ -648,7 +648,8 @@ static void close_channel(Channel *channel)
if (handle) {
uv_close(handle, close_cb);
} else {
- event_push((Event) { .handler = on_stdio_close, .data = channel }, false);
+ loop_push_event(&loop,
+ (Event) { .handler = on_stdio_close, .data = channel }, false);
}
}
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index 388b5a04cf..1a78b3498f 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -180,14 +180,14 @@ int server_start(const char *endpoint)
if (server_type == kServerTypeTcp) {
// Listen on tcp address/port
- uv_tcp_init(uv_default_loop(), &server->socket.tcp.handle);
+ uv_tcp_init(&loop.uv, &server->socket.tcp.handle);
result = uv_tcp_bind(&server->socket.tcp.handle,
(const struct sockaddr *)&server->socket.tcp.addr,
0);
stream = (uv_stream_t *)&server->socket.tcp.handle;
} else {
// Listen on named pipe or unix socket
- uv_pipe_init(uv_default_loop(), &server->socket.pipe.handle, 0);
+ uv_pipe_init(&loop.uv, &server->socket.pipe.handle, 0);
result = uv_pipe_bind(&server->socket.pipe.handle, server->addr);
stream = (uv_stream_t *)&server->socket.pipe.handle;
}
@@ -308,10 +308,10 @@ static void connection_cb(uv_stream_t *server, int status)
if (srv->type == kServerTypeTcp) {
client = xmalloc(sizeof(uv_tcp_t));
- uv_tcp_init(uv_default_loop(), (uv_tcp_t *)client);
+ uv_tcp_init(&loop.uv, (uv_tcp_t *)client);
} else {
client = xmalloc(sizeof(uv_pipe_t));
- uv_pipe_init(uv_default_loop(), (uv_pipe_t *)client, 0);
+ uv_pipe_init(&loop.uv, (uv_pipe_t *)client, 0);
}
result = uv_accept(server, client);
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 92734e404a..b66bc31b74 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -61,7 +61,7 @@
#include "nvim/mouse.h"
#include "nvim/undo.h"
#include "nvim/window.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/time.h"
/*
@@ -487,12 +487,12 @@ normal_cmd (
/*
* Get the command character from the user.
*/
- event_enable_deferred();
+ loop_enable_deferred_events(&loop);
c = safe_vgetc();
- event_disable_deferred();
+ loop_disable_deferred_events(&loop);
if (c == K_EVENT) {
- event_process();
+ loop_process_event(&loop);
return;
}
diff --git a/src/nvim/os/event.c b/src/nvim/os/event.c
deleted file mode 100644
index 56874b495d..0000000000
--- a/src/nvim/os/event.c
+++ /dev/null
@@ -1,177 +0,0 @@
-#include <assert.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <stdlib.h>
-
-#include <uv.h>
-
-#include "nvim/os/event.h"
-#include "nvim/os/input.h"
-#include "nvim/msgpack_rpc/defs.h"
-#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/msgpack_rpc/server.h"
-#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/os/signal.h"
-#include "nvim/os/rstream.h"
-#include "nvim/os/wstream.h"
-#include "nvim/os/job.h"
-#include "nvim/vim.h"
-#include "nvim/memory.h"
-#include "nvim/misc2.h"
-#include "nvim/ui.h"
-#include "nvim/screen.h"
-#include "nvim/terminal.h"
-
-#include "nvim/lib/klist.h"
-
-// event will be cleaned up after it gets processed
-#define _destroy_event(x) // do nothing
-KLIST_INIT(Event, Event, _destroy_event)
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "os/event.c.generated.h"
-#endif
-// deferred_events: Events that should be processed as the K_EVENT special key
-// immediate_events: Events that should be processed after exiting libuv event
-// loop(to avoid recursion), but before returning from
-// `event_poll`
-static klist_t(Event) *deferred_events = NULL, *immediate_events = NULL;
-static int deferred_events_allowed = 0;
-
-void event_init(void)
-{
- // Initialize the event queues
- deferred_events = kl_init(Event);
- immediate_events = kl_init(Event);
- // early msgpack-rpc initialization
- msgpack_rpc_init_method_table();
- msgpack_rpc_helpers_init();
- // Initialize input events
- input_init();
- // Timer to wake the event loop if a timeout argument is passed to
- // `event_poll`
- // Signals
- signal_init();
- // Jobs
- job_init();
- // finish mspgack-rpc initialization
- channel_init();
- server_init();
- terminal_init();
-}
-
-void event_teardown(void)
-{
- if (!deferred_events) {
- // Not initialized(possibly a --version invocation)
- return;
- }
-
- process_events_from(immediate_events);
- process_events_from(deferred_events);
- input_stop();
- channel_teardown();
- job_teardown();
- server_teardown();
- signal_teardown();
- terminal_teardown();
-
- // this last `uv_run` will return after all handles are stopped, it will
- // also take care of finishing any uv_close calls made by other *_teardown
- // functions.
- do {
- uv_run(uv_default_loop(), UV_RUN_DEFAULT);
- } while (uv_loop_close(uv_default_loop()));
-}
-
-// Wait for some event
-void event_poll(int ms)
-{
- static int recursive = 0;
-
- if (recursive++) {
- abort(); // Should not re-enter uv_run
- }
-
- uv_run_mode run_mode = UV_RUN_ONCE;
- uv_timer_t timer;
-
- if (ms > 0) {
- uv_timer_init(uv_default_loop(), &timer);
- // Use a repeating timeout of ms milliseconds to make sure
- // we do not block indefinitely for I/O.
- uv_timer_start(&timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
- } else if (ms == 0) {
- // For ms == 0, we need to do a non-blocking event poll by
- // setting the run mode to UV_RUN_NOWAIT.
- run_mode = UV_RUN_NOWAIT;
- }
-
- loop(run_mode);
-
- if (ms > 0) {
- // Ensure the timer handle is closed and run the event loop
- // once more to let libuv perform it's cleanup
- uv_timer_stop(&timer);
- uv_close((uv_handle_t *)&timer, NULL);
- loop(UV_RUN_NOWAIT);
- }
-
- recursive--; // Can re-enter uv_run now
-
- // In case this is run before event_init, don't process any events.
- if (immediate_events) {
- process_events_from(immediate_events);
- }
-}
-
-bool event_has_deferred(void)
-{
- return deferred_events_allowed && !kl_empty(deferred_events);
-}
-
-void event_enable_deferred(void)
-{
- ++deferred_events_allowed;
-}
-
-void event_disable_deferred(void)
-{
- --deferred_events_allowed;
-}
-
-// Queue an event
-void event_push(Event event, bool deferred)
-{
- // 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(uv_default_loop());
- kl_push(Event, deferred ? deferred_events : immediate_events, event);
-}
-
-void event_process(void)
-{
- process_events_from(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)
-{
-}
-
-static void loop(uv_run_mode run_mode)
-{
- DLOG("Enter event loop");
- uv_run(uv_default_loop(), run_mode);
- DLOG("Exit event loop");
-}
diff --git a/src/nvim/os/event_defs.h b/src/nvim/os/event_defs.h
deleted file mode 100644
index 2dd9403d9f..0000000000
--- a/src/nvim/os/event_defs.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef NVIM_OS_EVENT_DEFS_H
-#define NVIM_OS_EVENT_DEFS_H
-
-#include <stdbool.h>
-
-#include "nvim/os/job_defs.h"
-#include "nvim/os/rstream_defs.h"
-
-typedef struct event Event;
-typedef void (*event_handler)(Event event);
-
-struct event {
- void *data;
- event_handler handler;
-};
-
-#endif // NVIM_OS_EVENT_DEFS_H
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 726335bd9a..1449c56d59 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -6,7 +6,7 @@
#include "nvim/api/private/defs.h"
#include "nvim/os/input.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/rstream_defs.h"
#include "nvim/os/rstream.h"
#include "nvim/ascii.h"
@@ -115,7 +115,7 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
}
// If there are deferred events, return the keys directly
- if (event_has_deferred()) {
+ if (loop_has_deferred_events(&loop)) {
return push_event_key(buf, maxlen);
}
@@ -136,7 +136,7 @@ bool os_char_avail(void)
void os_breakcheck(void)
{
if (!disable_breakcheck && !got_int) {
- event_poll(0);
+ loop_poll_events(&loop, 0);
}
}
@@ -285,7 +285,7 @@ static bool input_poll(int ms)
prof_inchar_enter();
}
- event_poll_until(ms, input_ready() || input_eof);
+ LOOP_POLL_EVENTS_UNTIL(&loop, ms, input_ready() || input_eof);
if (do_profiling == PROF_YES && ms) {
prof_inchar_exit();
@@ -362,7 +362,7 @@ static bool input_ready(void)
{
return typebuf_was_filled || // API call filled typeahead
rbuffer_size(input_buffer) || // Input buffer filled
- event_has_deferred(); // Events must be processed
+ loop_has_deferred_events(&loop); // Events must be processed
}
// Exit because of an input read error.
diff --git a/src/nvim/os/job.c b/src/nvim/os/job.c
index f9bde21361..7e90994fb3 100644
--- a/src/nvim/os/job.c
+++ b/src/nvim/os/job.c
@@ -3,6 +3,9 @@
#include <uv.h>
+#include "nvim/event/loop.h"
+#include "nvim/event/time.h"
+#include "nvim/event/signal.h"
#include "nvim/os/uv_helpers.h"
#include "nvim/os/job.h"
#include "nvim/os/job_defs.h"
@@ -12,8 +15,6 @@
#include "nvim/os/rstream_defs.h"
#include "nvim/os/wstream.h"
#include "nvim/os/wstream_defs.h"
-#include "nvim/os/event.h"
-#include "nvim/os/event_defs.h"
#include "nvim/os/time.h"
#include "nvim/vim.h"
#include "nvim/memory.h"
@@ -45,8 +46,8 @@
Job *table[MAX_RUNNING_JOBS] = {NULL};
size_t stop_requests = 0;
-uv_timer_t job_stop_timer;
-uv_signal_t schld;
+TimeWatcher job_stop_timer;
+SignalWatcher schld;
// Some helpers shared in this module
@@ -59,9 +60,9 @@ uv_signal_t schld;
void job_init(void)
{
uv_disable_stdio_inheritance();
- uv_timer_init(uv_default_loop(), &job_stop_timer);
- uv_signal_init(uv_default_loop(), &schld);
- uv_signal_start(&schld, chld_handler, SIGCHLD);
+ time_watcher_init(&loop, &job_stop_timer, NULL);
+ signal_watcher_init(&loop, &schld, NULL);
+ signal_watcher_start(&schld, chld_handler, SIGCHLD);
}
/// Releases job control resources and terminates running jobs
@@ -78,11 +79,11 @@ void job_teardown(void)
}
// Wait until all jobs are closed
- event_poll_until(-1, !stop_requests);
- uv_signal_stop(&schld);
- uv_close((uv_handle_t *)&schld, NULL);
+ LOOP_POLL_EVENTS_UNTIL(&loop, -1, !stop_requests);
+ signal_watcher_stop(&schld);
+ signal_watcher_close(&schld, NULL);
// Close the timer
- uv_close((uv_handle_t *)&job_stop_timer, NULL);
+ time_watcher_close(&job_stop_timer, NULL);
}
/// Tries to start a new job.
@@ -152,7 +153,7 @@ Job *job_start(JobOptions opts, int *status)
uv_close((uv_handle_t *)job->proc_stderr, close_cb);
}
process_close(job);
- event_poll(0);
+ loop_poll_events(&loop, 0);
// Manually invoke the close_cb to free the job resources
*status = -1;
return NULL;
@@ -223,7 +224,7 @@ void job_stop(Job *job)
// When there's at least one stop request pending, start a timer that
// will periodically check if a signal should be send to a to the job
DLOG("Starting job kill timer");
- uv_timer_start(&job_stop_timer, job_stop_timer_cb, 100, 100);
+ time_watcher_start(&job_stop_timer, job_stop_timer_cb, 100, 100);
}
}
@@ -245,7 +246,7 @@ int job_wait(Job *job, int ms) FUNC_ATTR_NONNULL_ALL
// Increase refcount to stop the job from being freed before we have a
// chance to get the status.
job->refcount++;
- event_poll_until(ms,
+ LOOP_POLL_EVENTS_UNTIL(&loop, ms,
// Until...
got_int || // interrupted by the user
job->refcount == 1); // job exited
@@ -259,9 +260,9 @@ int job_wait(Job *job, int ms) FUNC_ATTR_NONNULL_ALL
if (ms == -1) {
// We can only return, if all streams/handles are closed and the job
// exited.
- event_poll_until(-1, job->refcount == 1);
+ LOOP_POLL_EVENTS_UNTIL(&loop, -1, job->refcount == 1);
} else {
- event_poll(0);
+ loop_poll_events(&loop, 0);
}
}
@@ -379,7 +380,7 @@ JobOptions *job_opts(Job *job)
/// Iterates the table, sending SIGTERM to stopped jobs and SIGKILL to those
/// that didn't die from SIGTERM after a while(exit_timeout is 0).
-static void job_stop_timer_cb(uv_timer_t *handle)
+static void job_stop_timer_cb(TimeWatcher *watcher, void *data)
{
Job *job;
uint64_t now = os_hrtime();
@@ -432,7 +433,7 @@ static void job_exited(Event event)
process_close(job);
}
-static void chld_handler(uv_signal_t *handle, int signum)
+static void chld_handler(SignalWatcher *watcher, int signum, void *data)
{
int stat = 0;
int pid;
@@ -458,7 +459,8 @@ static void chld_handler(uv_signal_t *handle, int signum)
// don't enqueue more events when exiting
process_close(job);
} else {
- event_push((Event) {.handler = job_exited, .data = job}, false);
+ loop_push_event(&loop,
+ (Event) {.handler = job_exited, .data = job}, false);
}
break;
}
diff --git a/src/nvim/os/job.h b/src/nvim/os/job.h
index e0ca615626..ed102666d0 100644
--- a/src/nvim/os/job.h
+++ b/src/nvim/os/job.h
@@ -11,7 +11,7 @@
#include <stdbool.h>
#include "nvim/os/rstream_defs.h"
-#include "nvim/os/event_defs.h"
+#include "nvim/os/job_defs.h"
#include "nvim/os/wstream.h"
#include "nvim/os/wstream_defs.h"
diff --git a/src/nvim/os/job_private.h b/src/nvim/os/job_private.h
index 983106d918..b90f2d0171 100644
--- a/src/nvim/os/job_private.h
+++ b/src/nvim/os/job_private.h
@@ -5,6 +5,7 @@
#include <uv.h>
+#include "nvim/event/time.h"
#include "nvim/os/rstream_defs.h"
#include "nvim/os/wstream_defs.h"
#include "nvim/os/pipe_process.h"
@@ -43,7 +44,7 @@ struct job {
extern Job *table[];
extern size_t stop_requests;
-extern uv_timer_t job_stop_timer;
+extern TimeWatcher job_stop_timer;
static inline bool process_spawn(Job *job)
{
@@ -95,7 +96,7 @@ static inline void job_exit_callback(Job *job)
if (stop_requests && !--stop_requests) {
// Stop the timer if no more stop requests are pending
DLOG("Stopping job kill timer");
- uv_timer_stop(&job_stop_timer);
+ time_watcher_stop(&job_stop_timer);
}
}
diff --git a/src/nvim/os/pipe_process.c b/src/nvim/os/pipe_process.c
index 2ac305e967..9980cf7c56 100644
--- a/src/nvim/os/pipe_process.c
+++ b/src/nvim/os/pipe_process.c
@@ -9,6 +9,8 @@
#include "nvim/os/job_private.h"
#include "nvim/os/pipe_process.h"
#include "nvim/memory.h"
+#include "nvim/vim.h"
+#include "nvim/globals.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pipe_process.c.generated.h"
@@ -46,19 +48,19 @@ void pipe_process_init(Job *job)
handle_set_job((uv_handle_t *)&pipeproc->proc, job);
if (job->opts.writable) {
- uv_pipe_init(uv_default_loop(), &pipeproc->proc_stdin, 0);
+ uv_pipe_init(&loop.uv, &pipeproc->proc_stdin, 0);
pipeproc->stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
pipeproc->stdio[0].data.stream = (uv_stream_t *)&pipeproc->proc_stdin;
}
if (job->opts.stdout_cb) {
- uv_pipe_init(uv_default_loop(), &pipeproc->proc_stdout, 0);
+ uv_pipe_init(&loop.uv, &pipeproc->proc_stdout, 0);
pipeproc->stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
pipeproc->stdio[1].data.stream = (uv_stream_t *)&pipeproc->proc_stdout;
}
if (job->opts.stderr_cb) {
- uv_pipe_init(uv_default_loop(), &pipeproc->proc_stderr, 0);
+ uv_pipe_init(&loop.uv, &pipeproc->proc_stderr, 0);
pipeproc->stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
pipeproc->stdio[2].data.stream = (uv_stream_t *)&pipeproc->proc_stderr;
}
@@ -81,7 +83,7 @@ bool pipe_process_spawn(Job *job)
{
UvProcess *pipeproc = job->process;
- if (uv_spawn(uv_default_loop(), &pipeproc->proc, &pipeproc->proc_opts) != 0) {
+ if (uv_spawn(&loop.uv, &pipeproc->proc, &pipeproc->proc_opts) != 0) {
return false;
}
diff --git a/src/nvim/os/pty_process.c b/src/nvim/os/pty_process.c
index ff0bcfb6de..ca74ebfddd 100644
--- a/src/nvim/os/pty_process.c
+++ b/src/nvim/os/pty_process.c
@@ -26,6 +26,8 @@
#include "nvim/os/job_private.h"
#include "nvim/os/pty_process.h"
#include "nvim/memory.h"
+#include "nvim/vim.h"
+#include "nvim/globals.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process.c.generated.h"
@@ -43,17 +45,17 @@ void pty_process_init(Job *job) FUNC_ATTR_NONNULL_ALL
ptyproc->tty_fd = -1;
if (job->opts.writable) {
- uv_pipe_init(uv_default_loop(), &ptyproc->proc_stdin, 0);
+ uv_pipe_init(&loop.uv, &ptyproc->proc_stdin, 0);
ptyproc->proc_stdin.data = NULL;
}
if (job->opts.stdout_cb) {
- uv_pipe_init(uv_default_loop(), &ptyproc->proc_stdout, 0);
+ uv_pipe_init(&loop.uv, &ptyproc->proc_stdout, 0);
ptyproc->proc_stdout.data = NULL;
}
if (job->opts.stderr_cb) {
- uv_pipe_init(uv_default_loop(), &ptyproc->proc_stderr, 0);
+ uv_pipe_init(&loop.uv, &ptyproc->proc_stderr, 0);
ptyproc->proc_stderr.data = NULL;
}
diff --git a/src/nvim/os/rstream.c b/src/nvim/os/rstream.c
index af84288f0f..dd91c2777e 100644
--- a/src/nvim/os/rstream.c
+++ b/src/nvim/os/rstream.c
@@ -120,7 +120,7 @@ void rstream_set_file(RStream *rstream, uv_file file)
// in chunks of rstream->buffer_size, giving time for other events to
// be processed between reads.
rstream->fread_idle = xmalloc(sizeof(uv_idle_t));
- uv_idle_init(uv_default_loop(), rstream->fread_idle);
+ uv_idle_init(&loop.uv, rstream->fread_idle);
rstream->fread_idle->data = NULL;
handle_set_rstream((uv_handle_t *)rstream->fread_idle, rstream);
} else {
@@ -128,7 +128,7 @@ void rstream_set_file(RStream *rstream, uv_file file)
assert(rstream->file_type == UV_NAMED_PIPE
|| rstream->file_type == UV_TTY);
rstream->stream = xmalloc(sizeof(uv_pipe_t));
- uv_pipe_init(uv_default_loop(), (uv_pipe_t *)rstream->stream, 0);
+ uv_pipe_init(&loop.uv, (uv_pipe_t *)rstream->stream, 0);
uv_pipe_open((uv_pipe_t *)rstream->stream, file);
rstream->stream->data = NULL;
handle_set_rstream((uv_handle_t *)rstream->stream, rstream);
@@ -224,7 +224,7 @@ static void fread_idle_cb(uv_idle_t *handle)
// Synchronous read
uv_fs_read(
- uv_default_loop(),
+ &loop.uv,
&req,
rstream->fd,
&rstream->uvbuf,
diff --git a/src/nvim/os/rstream.h b/src/nvim/os/rstream.h
index 3e24724573..7da77b33fa 100644
--- a/src/nvim/os/rstream.h
+++ b/src/nvim/os/rstream.h
@@ -4,7 +4,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <uv.h>
-#include "nvim/os/event_defs.h"
#include "nvim/os/rstream_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 48174533a6..9c0d5fca67 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -8,7 +8,7 @@
#include "nvim/ascii.h"
#include "nvim/lib/kvec.h"
#include "nvim/log.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/job.h"
#include "nvim/os/rstream.h"
#include "nvim/os/shell.h"
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index f824543003..6de3435c4c 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -11,12 +11,13 @@
#include "nvim/memory.h"
#include "nvim/misc1.h"
#include "nvim/misc2.h"
+#include "nvim/event/signal.h"
#include "nvim/os/signal.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
-static uv_signal_t spipe, shup, squit, sterm;
+static SignalWatcher spipe, shup, squit, sterm;
#ifdef SIGPWR
-static uv_signal_t spwr;
+static SignalWatcher spwr;
#endif
static bool rejecting_deadly;
@@ -27,40 +28,40 @@ static bool rejecting_deadly;
void signal_init(void)
{
- uv_signal_init(uv_default_loop(), &spipe);
- uv_signal_init(uv_default_loop(), &shup);
- uv_signal_init(uv_default_loop(), &squit);
- uv_signal_init(uv_default_loop(), &sterm);
- uv_signal_start(&spipe, signal_cb, SIGPIPE);
- uv_signal_start(&shup, signal_cb, SIGHUP);
- uv_signal_start(&squit, signal_cb, SIGQUIT);
- uv_signal_start(&sterm, signal_cb, SIGTERM);
+ signal_watcher_init(&loop, &spipe, NULL);
+ signal_watcher_init(&loop, &shup, NULL);
+ signal_watcher_init(&loop, &squit, NULL);
+ signal_watcher_init(&loop, &sterm, NULL);
+ signal_watcher_start(&spipe, on_signal, SIGPIPE);
+ signal_watcher_start(&shup, on_signal, SIGHUP);
+ signal_watcher_start(&squit, on_signal, SIGQUIT);
+ signal_watcher_start(&sterm, on_signal, SIGTERM);
#ifdef SIGPWR
- uv_signal_init(uv_default_loop(), &spwr);
- uv_signal_start(&spwr, signal_cb, SIGPWR);
+ signal_watcher_init(&loop, &spwr, NULL);
+ signal_watcher_start(&spwr, on_signal, SIGPWR);
#endif
}
void signal_teardown(void)
{
signal_stop();
- uv_close((uv_handle_t *)&spipe, NULL);
- uv_close((uv_handle_t *)&shup, NULL);
- uv_close((uv_handle_t *)&squit, NULL);
- uv_close((uv_handle_t *)&sterm, NULL);
+ signal_watcher_close(&spipe, NULL);
+ signal_watcher_close(&shup, NULL);
+ signal_watcher_close(&squit, NULL);
+ signal_watcher_close(&sterm, NULL);
#ifdef SIGPWR
- uv_close((uv_handle_t *)&spwr, NULL);
+ signal_watcher_close(&spwr, NULL);
#endif
}
void signal_stop(void)
{
- uv_signal_stop(&spipe);
- uv_signal_stop(&shup);
- uv_signal_stop(&squit);
- uv_signal_stop(&sterm);
+ signal_watcher_stop(&spipe);
+ signal_watcher_stop(&shup);
+ signal_watcher_stop(&squit);
+ signal_watcher_stop(&sterm);
#ifdef SIGPWR
- uv_signal_stop(&spwr);
+ signal_watcher_stop(&spwr);
#endif
}
@@ -111,10 +112,10 @@ static void deadly_signal(int signum)
preserve_exit();
}
-static void signal_cb(uv_signal_t *handle, int signum)
+static void on_signal(SignalWatcher *handle, int signum, void *data)
{
assert(signum >= 0);
- event_push((Event) {
+ loop_push_event(&loop, (Event) {
.handler = on_signal_event,
.data = (void *)(uintptr_t)signum
}, false);
diff --git a/src/nvim/os/signal.h b/src/nvim/os/signal.h
index 927437b2db..5d8cc6f661 100644
--- a/src/nvim/os/signal.h
+++ b/src/nvim/os/signal.h
@@ -1,8 +1,6 @@
#ifndef NVIM_OS_SIGNAL_H
#define NVIM_OS_SIGNAL_H
-#include "nvim/os/event_defs.h"
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/signal.h.generated.h"
#endif
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index 590dfba797..6b5d4359db 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -7,7 +7,7 @@
#include <uv.h>
#include "nvim/os/time.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/vim.h"
static uv_mutex_t delay_mutex;
@@ -43,7 +43,7 @@ void os_delay(uint64_t milliseconds, bool ignoreinput)
if (milliseconds > INT_MAX) {
milliseconds = INT_MAX;
}
- event_poll_until((int)milliseconds, got_int);
+ LOOP_POLL_EVENTS_UNTIL(&loop, (int)milliseconds, got_int);
} else {
os_microdelay(milliseconds * 1000);
}
diff --git a/src/nvim/os/wstream.c b/src/nvim/os/wstream.c
index 73896c381d..7f5191947a 100644
--- a/src/nvim/os/wstream.c
+++ b/src/nvim/os/wstream.c
@@ -103,7 +103,7 @@ void wstream_set_file(WStream *wstream, uv_file file)
assert(uv_guess_handle(file) == UV_NAMED_PIPE ||
uv_guess_handle(file) == UV_TTY);
wstream->stream = xmalloc(sizeof(uv_pipe_t));
- uv_pipe_init(uv_default_loop(), (uv_pipe_t *)wstream->stream, 0);
+ uv_pipe_init(&loop.uv, (uv_pipe_t *)wstream->stream, 0);
uv_pipe_open((uv_pipe_t *)wstream->stream, file);
wstream->stream->data = NULL;
handle_set_wstream((uv_handle_t *)wstream->stream, wstream);
diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c
index ccd0073db1..f568f5a7f1 100644
--- a/src/nvim/os_unix.c
+++ b/src/nvim/os_unix.c
@@ -47,13 +47,11 @@
#include "nvim/types.h"
#include "nvim/os/os.h"
#include "nvim/os/time.h"
-#include "nvim/os/event.h"
#include "nvim/os/input.h"
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/os/job.h"
#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/msgpack_rpc/defs.h"
#ifdef HAVE_STROPTS_H
# include <stropts.h>
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 9ce050ed7a..47fef692db 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -67,7 +67,8 @@
#include "nvim/ex_cmds.h"
#include "nvim/window.h"
#include "nvim/fileio.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/time.h"
#include "nvim/api/private/helpers.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -80,7 +81,7 @@
// of data.
#define REFRESH_DELAY 10
-static uv_timer_t refresh_timer;
+static TimeWatcher refresh_timer;
static bool refresh_pending = false;
typedef struct {
@@ -150,7 +151,7 @@ static VTermColor default_vt_bg_rgb;
void terminal_init(void)
{
invalidated_terminals = pmap_new(ptr_t)();
- uv_timer_init(uv_default_loop(), &refresh_timer);
+ time_watcher_init(&loop, &refresh_timer, NULL);
// initialize a rgb->color index map for cterm attributes(VTermScreenCell
// only has RGB information and we need color indexes for terminal UIs)
@@ -175,8 +176,8 @@ void terminal_init(void)
void terminal_teardown(void)
{
- uv_timer_stop(&refresh_timer);
- uv_close((uv_handle_t *)&refresh_timer, NULL);
+ time_watcher_stop(&refresh_timer);
+ time_watcher_close(&refresh_timer, NULL);
pmap_free(ptr_t)(invalidated_terminals);
map_free(int, int)(color_indexes);
}
@@ -353,13 +354,13 @@ void terminal_enter(bool process_deferred)
while (term->buf == curbuf) {
if (process_deferred) {
- event_enable_deferred();
+ loop_enable_deferred_events(&loop);
}
c = safe_vgetc();
if (process_deferred) {
- event_disable_deferred();
+ loop_disable_deferred_events(&loop);
}
switch (c) {
@@ -380,7 +381,7 @@ void terminal_enter(bool process_deferred)
break;
case K_EVENT:
- event_process();
+ loop_process_event(&loop);
break;
case Ctrl_N:
@@ -877,16 +878,16 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row)
pmap_put(ptr_t)(invalidated_terminals, term, NULL);
if (!refresh_pending) {
- uv_timer_start(&refresh_timer, refresh_timer_cb, REFRESH_DELAY, 0);
+ time_watcher_start(&refresh_timer, refresh_timer_cb, REFRESH_DELAY, 0);
refresh_pending = true;
}
}
// libuv timer callback. This will enqueue on_refresh to be processed as an
// event.
-static void refresh_timer_cb(uv_timer_t *handle)
+static void refresh_timer_cb(TimeWatcher *watcher, void *data)
{
- event_push((Event) {.handler = on_refresh}, false);
+ loop_push_event(&loop, (Event) {.handler = on_refresh}, false);
refresh_pending = false;
}
diff --git a/src/nvim/tui/term_input.inl b/src/nvim/tui/term_input.inl
index efdcf0a41e..331a0a89e0 100644
--- a/src/nvim/tui/term_input.inl
+++ b/src/nvim/tui/term_input.inl
@@ -5,6 +5,7 @@
#include "nvim/os/os.h"
#include "nvim/os/input.h"
#include "nvim/os/rstream.h"
+#include "nvim/event/time.h"
#define PASTETOGGLE_KEY "<f37>"
@@ -12,7 +13,7 @@ struct term_input {
int in_fd;
bool paste_enabled;
TermKey *tk;
- uv_timer_t timer_handle;
+ TimeWatcher timer_handle;
RBuffer *read_buffer;
RStream *read_stream;
};
@@ -107,7 +108,7 @@ static TermKeyResult tk_getkey(TermKey *tk, TermKeyKey *key, bool force)
return force ? termkey_getkey_force(tk, key) : termkey_getkey(tk, key);
}
-static void timer_cb(uv_timer_t *handle);
+static void timer_cb(TimeWatcher *watcher, void *data);
static int get_key_code_timeout(void)
{
@@ -147,17 +148,16 @@ static void tk_getkeys(TermInput *input, bool force)
if (ms > 0) {
// Stop the current timer if already running
- uv_timer_stop(&input->timer_handle);
- uv_timer_start(&input->timer_handle, timer_cb, (uint32_t)ms, 0);
+ time_watcher_stop(&input->timer_handle);
+ time_watcher_start(&input->timer_handle, timer_cb, (uint32_t)ms, 0);
} else {
tk_getkeys(input, true);
}
}
-
-static void timer_cb(uv_timer_t *handle)
+static void timer_cb(TimeWatcher *watcher, void *data)
{
- tk_getkeys(handle->data, true);
+ tk_getkeys(data, true);
}
static bool handle_bracketed_paste(TermInput *input)
@@ -288,8 +288,7 @@ static TermInput *term_input_new(void)
rstream_set_file(rv->read_stream, rv->in_fd);
rstream_start(rv->read_stream);
// initialize a timer handle for handling ESC with libtermkey
- uv_timer_init(uv_default_loop(), &rv->timer_handle);
- rv->timer_handle.data = rv;
+ time_watcher_init(&loop, &rv->timer_handle, rv);
// Set the pastetoggle option to a special key that will be sent when
// \e[20{0,1}~/ are received
Error err = ERROR_INIT;
@@ -300,12 +299,13 @@ static TermInput *term_input_new(void)
static void term_input_destroy(TermInput *input)
{
- uv_timer_stop(&input->timer_handle);
+ time_watcher_stop(&input->timer_handle);
+ time_watcher_close(&input->timer_handle, NULL);
rstream_stop(input->read_stream);
rstream_free(input->read_stream);
- uv_close((uv_handle_t *)&input->timer_handle, NULL);
termkey_destroy(input->tk);
- event_poll(0); // Run once to remove references to input/timer handles
+ // Run once to remove references to input/timer handles
+ loop_poll_events(&loop, 0);
xfree(input);
}
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index fe29dbd961..a12ee880d6 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -13,7 +13,8 @@
#include "nvim/memory.h"
#include "nvim/api/vim.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/signal.h"
#include "nvim/tui/tui.h"
#include "nvim/strings.h"
@@ -43,7 +44,7 @@ typedef struct {
uv_loop_t *write_loop;
unibi_term *ut;
uv_tty_t output_handle;
- uv_signal_t winch_handle;
+ SignalWatcher winch_handle;
Rect scroll_region;
kvec_t(Rect) invalid_regions;
int row, col;
@@ -132,9 +133,8 @@ UI *tui_start(void)
update_size(ui);
// listen for SIGWINCH
- uv_signal_init(uv_default_loop(), &data->winch_handle);
- uv_signal_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
- data->winch_handle.data = ui;
+ signal_watcher_init(&loop, &data->winch_handle, ui);
+ signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
ui->stop = tui_stop;
ui->rgb = os_getenv("NVIM_TUI_ENABLE_TRUE_COLOR") != NULL;
@@ -172,8 +172,8 @@ static void tui_stop(UI *ui)
TUIData *data = ui->data;
// Destroy common stuff
kv_destroy(data->invalid_regions);
- uv_signal_stop(&data->winch_handle);
- uv_close((uv_handle_t *)&data->winch_handle, NULL);
+ signal_watcher_stop(&data->winch_handle);
+ signal_watcher_close(&data->winch_handle, NULL);
// Destroy input stuff
term_input_destroy(data->input);
// Destroy output stuff
@@ -207,12 +207,12 @@ static void try_resize(Event ev)
ui_refresh();
}
-static void sigwinch_cb(uv_signal_t *handle, int signum)
+static void sigwinch_cb(SignalWatcher *watcher, int signum, void *data)
{
// Queue the event because resizing can result in recursive event_poll calls
// FIXME(blueyed): TUI does not resize properly when not deferred. Why? #2322
- event_push((Event) {
- .data = handle->data,
+ loop_push_event(&loop, (Event) {
+ .data = data,
.handler = try_resize
}, true);
}
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 088055777a..dc2bc0898c 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -23,7 +23,7 @@
#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/os_unix.h"
-#include "nvim/os/event.h"
+#include "nvim/event/loop.h"
#include "nvim/os/time.h"
#include "nvim/os/input.h"
#include "nvim/os/signal.h"
@@ -216,7 +216,7 @@ void ui_detach(UI *ui)
ui_count--;
// schedule a refresh
- event_push((Event) { .handler = refresh }, false);
+ loop_push_event(&loop, (Event) { .handler = refresh }, false);
}
void ui_clear(void)
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua
index 3d5c6bc885..2ffffb907f 100644
--- a/test/unit/os/fs_spec.lua
+++ b/test/unit/os/fs_spec.lua
@@ -19,7 +19,7 @@ require('bit')
cimport('unistd.h')
cimport('./src/nvim/os/shell.h')
cimport('./src/nvim/option_defs.h')
-cimport('./src/nvim/os/event.h')
+cimport('./src/nvim/main.h')
cimport('./src/nvim/fileio.h')
local fs = cimport('./src/nvim/os/os.h')
cppimport('sys/stat.h')
diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua
index 91d807da0b..91123bfd58 100644
--- a/test/unit/os/shell_spec.lua
+++ b/test/unit/os/shell_spec.lua
@@ -14,7 +14,7 @@ local helpers = require('test.unit.helpers')
local shell = helpers.cimport(
'./src/nvim/os/shell.h',
'./src/nvim/option_defs.h',
- './src/nvim/os/event.h',
+ './src/nvim/main.h',
'./src/nvim/misc1.h'
)
local ffi, eq, neq = helpers.ffi, helpers.eq, helpers.neq