mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	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.
This commit is contained in:
		@@ -30,15 +30,17 @@ file(MAKE_DIRECTORY ${GENERATED_DIR}/api)
 | 
				
			|||||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/api/private)
 | 
					file(MAKE_DIRECTORY ${GENERATED_DIR}/api/private)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/msgpack_rpc)
 | 
					file(MAKE_DIRECTORY ${GENERATED_DIR}/msgpack_rpc)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_DIR}/tui)
 | 
					file(MAKE_DIRECTORY ${GENERATED_DIR}/tui)
 | 
				
			||||||
 | 
					file(MAKE_DIRECTORY ${GENERATED_DIR}/event)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR})
 | 
					file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR})
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/os)
 | 
					file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/os)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api)
 | 
					file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api/private)
 | 
					file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/api/private)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/msgpack_rpc)
 | 
					file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/msgpack_rpc)
 | 
				
			||||||
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/tui)
 | 
					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
 | 
					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_RECURSE NEOVIM_HEADERS *.h)
 | 
				
			||||||
file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
 | 
					file(GLOB UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,7 +59,7 @@
 | 
				
			|||||||
#include "nvim/terminal.h"
 | 
					#include "nvim/terminal.h"
 | 
				
			||||||
#include "nvim/undo.h"
 | 
					#include "nvim/undo.h"
 | 
				
			||||||
#include "nvim/window.h"
 | 
					#include "nvim/window.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
#include "nvim/os/time.h"
 | 
					#include "nvim/os/time.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -601,15 +601,15 @@ edit (
 | 
				
			|||||||
     * Get a character for Insert mode.  Ignore K_IGNORE.
 | 
					     * Get a character for Insert mode.  Ignore K_IGNORE.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    lastc = c;                          /* remember previous char for CTRL-D */
 | 
					    lastc = c;                          /* remember previous char for CTRL-D */
 | 
				
			||||||
    event_enable_deferred();
 | 
					    loop_enable_deferred_events(&loop);
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
      c = safe_vgetc();
 | 
					      c = safe_vgetc();
 | 
				
			||||||
    } while (c == K_IGNORE);
 | 
					    } while (c == K_IGNORE);
 | 
				
			||||||
    event_disable_deferred();
 | 
					    loop_disable_deferred_events(&loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c == K_EVENT) {
 | 
					    if (c == K_EVENT) {
 | 
				
			||||||
      c = lastc;
 | 
					      c = lastc;
 | 
				
			||||||
      event_process();
 | 
					      loop_process_event(&loop);
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,8 +91,8 @@
 | 
				
			|||||||
#include "nvim/api/private/helpers.h"
 | 
					#include "nvim/api/private/helpers.h"
 | 
				
			||||||
#include "nvim/api/vim.h"
 | 
					#include "nvim/api/vim.h"
 | 
				
			||||||
#include "nvim/os/dl.h"
 | 
					#include "nvim/os/dl.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					 | 
				
			||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DICT_MAXNEST 100        /* maximum nesting of lists and dicts */
 | 
					#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++) {
 | 
					  if (!disable_job_defer++) {
 | 
				
			||||||
    // process any pending job events in the deferred queue, but only do this if
 | 
					    // process any pending job events in the deferred queue, but only do this if
 | 
				
			||||||
    // deferred is not disabled(at the top-level `jobwait()` call)
 | 
					    // 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
 | 
					  // 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
 | 
					  // 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
 | 
					  // 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) {
 | 
					  for (listitem_T *arg = args->lv_first; arg != NULL; arg = arg->li_next) {
 | 
				
			||||||
    Job *job = NULL;
 | 
					    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->data = job_data(job);
 | 
				
			||||||
  event_data->callback = callback;
 | 
					  event_data->callback = callback;
 | 
				
			||||||
  event_data->type = type;
 | 
					  event_data->type = type;
 | 
				
			||||||
  event_push((Event) {
 | 
					  loop_push_event(&loop, (Event) {
 | 
				
			||||||
    .handler = on_job_event,
 | 
					    .handler = on_job_event,
 | 
				
			||||||
    .data = event_data
 | 
					    .data = event_data
 | 
				
			||||||
  }, !disable_job_defer);
 | 
					  }, !disable_job_defer);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										137
									
								
								src/nvim/event/loop.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										137
									
								
								src/nvim/event/loop.c
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,20 +1,40 @@
 | 
				
			|||||||
#ifndef NVIM_OS_EVENT_H
 | 
					#ifndef NVIM_EVENT_LOOP_H
 | 
				
			||||||
#define NVIM_OS_EVENT_H
 | 
					#define NVIM_EVENT_LOOP_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "nvim/os/event_defs.h"
 | 
					#include <uv.h>
 | 
				
			||||||
#include "nvim/os/job_defs.h"
 | 
					
 | 
				
			||||||
 | 
					#include "nvim/lib/klist.h"
 | 
				
			||||||
#include "nvim/os/time.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
 | 
					// Poll for events until a condition or timeout
 | 
				
			||||||
#define event_poll_until(timeout, condition)                                 \
 | 
					#define LOOP_POLL_EVENTS_UNTIL(loop, timeout, condition)                     \
 | 
				
			||||||
  do {                                                                       \
 | 
					  do {                                                                       \
 | 
				
			||||||
    int remaining = timeout;                                                 \
 | 
					    int remaining = timeout;                                                 \
 | 
				
			||||||
    uint64_t before = (remaining > 0) ? os_hrtime() : 0;                     \
 | 
					    uint64_t before = (remaining > 0) ? os_hrtime() : 0;                     \
 | 
				
			||||||
    while (!(condition)) {                                                   \
 | 
					    while (!(condition)) {                                                   \
 | 
				
			||||||
      event_poll(remaining);                                                 \
 | 
					      loop_poll_events(loop, remaining);                                     \
 | 
				
			||||||
      if (remaining == 0) {                                                  \
 | 
					      if (remaining == 0) {                                                  \
 | 
				
			||||||
        break;                                                               \
 | 
					        break;                                                               \
 | 
				
			||||||
      } else if (remaining > 0) {                                            \
 | 
					      } else if (remaining > 0) {                                            \
 | 
				
			||||||
@@ -29,7 +49,7 @@
 | 
				
			|||||||
  } while (0)
 | 
					  } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
# include "os/event.h.generated.h"
 | 
					# include "event/loop.h.generated.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif  // NVIM_OS_EVENT_H
 | 
					#endif  // NVIM_EVENT_LOOP_H
 | 
				
			||||||
							
								
								
									
										52
									
								
								src/nvim/event/signal.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/nvim/event/signal.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/nvim/event/signal.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/nvim/event/signal.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
							
								
								
									
										55
									
								
								src/nvim/event/time.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/nvim/event/time.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										20
									
								
								src/nvim/event/time.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/nvim/event/time.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
				
			||||||
@@ -63,7 +63,7 @@
 | 
				
			|||||||
#include "nvim/window.h"
 | 
					#include "nvim/window.h"
 | 
				
			||||||
#include "nvim/ui.h"
 | 
					#include "nvim/ui.h"
 | 
				
			||||||
#include "nvim/os/os.h"
 | 
					#include "nvim/os/os.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Variables shared between getcmdline(), redrawcmdline() and others.
 | 
					 * Variables shared between getcmdline(), redrawcmdline() and others.
 | 
				
			||||||
@@ -298,14 +298,14 @@ getcmdline (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* Get a character.  Ignore K_IGNORE, it should not do anything, such
 | 
					    /* Get a character.  Ignore K_IGNORE, it should not do anything, such
 | 
				
			||||||
     * as stop completion. */
 | 
					     * as stop completion. */
 | 
				
			||||||
    event_enable_deferred();
 | 
					    loop_enable_deferred_events(&loop);
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
      c = safe_vgetc();
 | 
					      c = safe_vgetc();
 | 
				
			||||||
    } while (c == K_IGNORE);
 | 
					    } while (c == K_IGNORE);
 | 
				
			||||||
    event_disable_deferred();
 | 
					    loop_disable_deferred_events(&loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (c == K_EVENT) {
 | 
					    if (c == K_EVENT) {
 | 
				
			||||||
      event_process();
 | 
					      loop_process_event(&loop);
 | 
				
			||||||
      continue;
 | 
					      continue;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,7 @@
 | 
				
			|||||||
#include "nvim/strings.h"
 | 
					#include "nvim/strings.h"
 | 
				
			||||||
#include "nvim/ui.h"
 | 
					#include "nvim/ui.h"
 | 
				
			||||||
#include "nvim/undo.h"
 | 
					#include "nvim/undo.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
#include "nvim/os/os.h"
 | 
					#include "nvim/os/os.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@
 | 
				
			|||||||
#include "nvim/menu.h"
 | 
					#include "nvim/menu.h"
 | 
				
			||||||
#include "nvim/syntax_defs.h"
 | 
					#include "nvim/syntax_defs.h"
 | 
				
			||||||
#include "nvim/types.h"
 | 
					#include "nvim/types.h"
 | 
				
			||||||
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * definition of global variables
 | 
					 * definition of global variables
 | 
				
			||||||
@@ -1216,6 +1217,7 @@ EXTERN char *ignoredp;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// If a msgpack-rpc channel should be started over stdin/stdout
 | 
					// If a msgpack-rpc channel should be started over stdin/stdout
 | 
				
			||||||
EXTERN bool embedded_mode INIT(= false);
 | 
					EXTERN bool embedded_mode INIT(= false);
 | 
				
			||||||
 | 
					EXTERN Loop loop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Used to track the status of external functions.
 | 
					/// Used to track the status of external functions.
 | 
				
			||||||
/// Currently only used for iconv().
 | 
					/// Currently only used for iconv().
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,9 +61,13 @@
 | 
				
			|||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
#include "nvim/os/os.h"
 | 
					#include "nvim/os/os.h"
 | 
				
			||||||
#include "nvim/os/time.h"
 | 
					#include "nvim/os/time.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/os/signal.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/helpers.h"
 | 
				
			||||||
 | 
					#include "nvim/msgpack_rpc/server.h"
 | 
				
			||||||
 | 
					#include "nvim/msgpack_rpc/channel.h"
 | 
				
			||||||
#include "nvim/api/private/defs.h"
 | 
					#include "nvim/api/private/defs.h"
 | 
				
			||||||
#include "nvim/api/private/helpers.h"
 | 
					#include "nvim/api/private/helpers.h"
 | 
				
			||||||
#include "nvim/api/private/handle.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");
 | 
					  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.
 | 
					/// Performs early initialization.
 | 
				
			||||||
///
 | 
					///
 | 
				
			||||||
/// Needed for unit tests. Must be called after `time_init()`.
 | 
					/// Needed for unit tests. Must be called after `time_init()`.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,7 +9,7 @@
 | 
				
			|||||||
#include "nvim/api/vim.h"
 | 
					#include "nvim/api/vim.h"
 | 
				
			||||||
#include "nvim/msgpack_rpc/channel.h"
 | 
					#include "nvim/msgpack_rpc/channel.h"
 | 
				
			||||||
#include "nvim/msgpack_rpc/remote_ui.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.h"
 | 
				
			||||||
#include "nvim/os/rstream_defs.h"
 | 
					#include "nvim/os/rstream_defs.h"
 | 
				
			||||||
#include "nvim/os/wstream.h"
 | 
					#include "nvim/os/wstream.h"
 | 
				
			||||||
@@ -220,7 +220,7 @@ Object channel_send_call(uint64_t id,
 | 
				
			|||||||
  ChannelCallFrame frame = {request_id, false, false, NIL};
 | 
					  ChannelCallFrame frame = {request_id, false, false, NIL};
 | 
				
			||||||
  kv_push(ChannelCallFrame *, channel->call_stack, &frame);
 | 
					  kv_push(ChannelCallFrame *, channel->call_stack, &frame);
 | 
				
			||||||
  channel->pending_requests++;
 | 
					  channel->pending_requests++;
 | 
				
			||||||
  event_poll_until(-1, frame.returned);
 | 
					  LOOP_POLL_EVENTS_UNTIL(&loop, -1, frame.returned);
 | 
				
			||||||
  (void)kv_pop(channel->call_stack);
 | 
					  (void)kv_pop(channel->call_stack);
 | 
				
			||||||
  channel->pending_requests--;
 | 
					  channel->pending_requests--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -474,7 +474,7 @@ static void handle_request(Channel *channel, msgpack_object *request)
 | 
				
			|||||||
  event_data->args = args;
 | 
					  event_data->args = args;
 | 
				
			||||||
  event_data->request_id = request_id;
 | 
					  event_data->request_id = request_id;
 | 
				
			||||||
  incref(channel);
 | 
					  incref(channel);
 | 
				
			||||||
  event_push((Event) {
 | 
					  loop_push_event(&loop, (Event) {
 | 
				
			||||||
    .handler = on_request_event,
 | 
					    .handler = on_request_event,
 | 
				
			||||||
    .data = event_data
 | 
					    .data = event_data
 | 
				
			||||||
  }, defer);
 | 
					  }, defer);
 | 
				
			||||||
@@ -648,7 +648,8 @@ static void close_channel(Channel *channel)
 | 
				
			|||||||
    if (handle) {
 | 
					    if (handle) {
 | 
				
			||||||
      uv_close(handle, close_cb);
 | 
					      uv_close(handle, close_cb);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      event_push((Event) { .handler = on_stdio_close, .data = channel }, false);
 | 
					      loop_push_event(&loop,
 | 
				
			||||||
 | 
					          (Event) { .handler = on_stdio_close, .data = channel }, false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -180,14 +180,14 @@ int server_start(const char *endpoint)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (server_type == kServerTypeTcp) {
 | 
					  if (server_type == kServerTypeTcp) {
 | 
				
			||||||
    // Listen on tcp address/port
 | 
					    // 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,
 | 
					    result = uv_tcp_bind(&server->socket.tcp.handle,
 | 
				
			||||||
                         (const struct sockaddr *)&server->socket.tcp.addr,
 | 
					                         (const struct sockaddr *)&server->socket.tcp.addr,
 | 
				
			||||||
                         0);
 | 
					                         0);
 | 
				
			||||||
    stream = (uv_stream_t *)&server->socket.tcp.handle;
 | 
					    stream = (uv_stream_t *)&server->socket.tcp.handle;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    // Listen on named pipe or unix socket
 | 
					    // 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);
 | 
					    result = uv_pipe_bind(&server->socket.pipe.handle, server->addr);
 | 
				
			||||||
    stream = (uv_stream_t *)&server->socket.pipe.handle;
 | 
					    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) {
 | 
					  if (srv->type == kServerTypeTcp) {
 | 
				
			||||||
    client = xmalloc(sizeof(uv_tcp_t));
 | 
					    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 {
 | 
					  } else {
 | 
				
			||||||
    client = xmalloc(sizeof(uv_pipe_t));
 | 
					    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);
 | 
					  result = uv_accept(server, client);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,7 +61,7 @@
 | 
				
			|||||||
#include "nvim/mouse.h"
 | 
					#include "nvim/mouse.h"
 | 
				
			||||||
#include "nvim/undo.h"
 | 
					#include "nvim/undo.h"
 | 
				
			||||||
#include "nvim/window.h"
 | 
					#include "nvim/window.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/os/time.h"
 | 
					#include "nvim/os/time.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -487,12 +487,12 @@ normal_cmd (
 | 
				
			|||||||
  /*
 | 
					  /*
 | 
				
			||||||
   * Get the command character from the user.
 | 
					   * Get the command character from the user.
 | 
				
			||||||
   */
 | 
					   */
 | 
				
			||||||
  event_enable_deferred();
 | 
					  loop_enable_deferred_events(&loop);
 | 
				
			||||||
  c = safe_vgetc();
 | 
					  c = safe_vgetc();
 | 
				
			||||||
  event_disable_deferred();
 | 
					  loop_disable_deferred_events(&loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (c == K_EVENT) {
 | 
					  if (c == K_EVENT) {
 | 
				
			||||||
    event_process();
 | 
					    loop_process_event(&loop);
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -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
 | 
					 | 
				
			||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "nvim/api/private/defs.h"
 | 
					#include "nvim/api/private/defs.h"
 | 
				
			||||||
#include "nvim/os/input.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_defs.h"
 | 
				
			||||||
#include "nvim/os/rstream.h"
 | 
					#include "nvim/os/rstream.h"
 | 
				
			||||||
#include "nvim/ascii.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 there are deferred events, return the keys directly
 | 
				
			||||||
  if (event_has_deferred()) {
 | 
					  if (loop_has_deferred_events(&loop)) {
 | 
				
			||||||
    return push_event_key(buf, maxlen);
 | 
					    return push_event_key(buf, maxlen);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -136,7 +136,7 @@ bool os_char_avail(void)
 | 
				
			|||||||
void os_breakcheck(void)
 | 
					void os_breakcheck(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (!disable_breakcheck && !got_int) {
 | 
					  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();
 | 
					    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) {
 | 
					  if (do_profiling == PROF_YES && ms) {
 | 
				
			||||||
    prof_inchar_exit();
 | 
					    prof_inchar_exit();
 | 
				
			||||||
@@ -362,7 +362,7 @@ static bool input_ready(void)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  return typebuf_was_filled ||                 // API call filled typeahead
 | 
					  return typebuf_was_filled ||                 // API call filled typeahead
 | 
				
			||||||
         rbuffer_size(input_buffer) ||         // Input buffer filled
 | 
					         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.
 | 
					// Exit because of an input read error.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <uv.h>
 | 
					#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/uv_helpers.h"
 | 
				
			||||||
#include "nvim/os/job.h"
 | 
					#include "nvim/os/job.h"
 | 
				
			||||||
#include "nvim/os/job_defs.h"
 | 
					#include "nvim/os/job_defs.h"
 | 
				
			||||||
@@ -12,8 +15,6 @@
 | 
				
			|||||||
#include "nvim/os/rstream_defs.h"
 | 
					#include "nvim/os/rstream_defs.h"
 | 
				
			||||||
#include "nvim/os/wstream.h"
 | 
					#include "nvim/os/wstream.h"
 | 
				
			||||||
#include "nvim/os/wstream_defs.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/os/time.h"
 | 
				
			||||||
#include "nvim/vim.h"
 | 
					#include "nvim/vim.h"
 | 
				
			||||||
#include "nvim/memory.h"
 | 
					#include "nvim/memory.h"
 | 
				
			||||||
@@ -45,8 +46,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
Job *table[MAX_RUNNING_JOBS] = {NULL};
 | 
					Job *table[MAX_RUNNING_JOBS] = {NULL};
 | 
				
			||||||
size_t stop_requests = 0;
 | 
					size_t stop_requests = 0;
 | 
				
			||||||
uv_timer_t job_stop_timer;
 | 
					TimeWatcher job_stop_timer;
 | 
				
			||||||
uv_signal_t schld;
 | 
					SignalWatcher schld;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Some helpers shared in this module
 | 
					// Some helpers shared in this module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,9 +60,9 @@ uv_signal_t schld;
 | 
				
			|||||||
void job_init(void)
 | 
					void job_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  uv_disable_stdio_inheritance();
 | 
					  uv_disable_stdio_inheritance();
 | 
				
			||||||
  uv_timer_init(uv_default_loop(), &job_stop_timer);
 | 
					  time_watcher_init(&loop, &job_stop_timer, NULL);
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &schld);
 | 
					  signal_watcher_init(&loop, &schld, NULL);
 | 
				
			||||||
  uv_signal_start(&schld, chld_handler, SIGCHLD);
 | 
					  signal_watcher_start(&schld, chld_handler, SIGCHLD);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Releases job control resources and terminates running jobs
 | 
					/// Releases job control resources and terminates running jobs
 | 
				
			||||||
@@ -78,11 +79,11 @@ void job_teardown(void)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Wait until all jobs are closed
 | 
					  // Wait until all jobs are closed
 | 
				
			||||||
  event_poll_until(-1, !stop_requests);
 | 
					  LOOP_POLL_EVENTS_UNTIL(&loop, -1, !stop_requests);
 | 
				
			||||||
  uv_signal_stop(&schld);
 | 
					  signal_watcher_stop(&schld);
 | 
				
			||||||
  uv_close((uv_handle_t *)&schld, NULL);
 | 
					  signal_watcher_close(&schld, NULL);
 | 
				
			||||||
  // Close the timer
 | 
					  // 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.
 | 
					/// 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);
 | 
					      uv_close((uv_handle_t *)job->proc_stderr, close_cb);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    process_close(job);
 | 
					    process_close(job);
 | 
				
			||||||
    event_poll(0);
 | 
					    loop_poll_events(&loop, 0);
 | 
				
			||||||
    // Manually invoke the close_cb to free the job resources
 | 
					    // Manually invoke the close_cb to free the job resources
 | 
				
			||||||
    *status = -1;
 | 
					    *status = -1;
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
@@ -223,7 +224,7 @@ void job_stop(Job *job)
 | 
				
			|||||||
    // When there's at least one stop request pending, start a timer that
 | 
					    // 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
 | 
					    // will periodically check if a signal should be send to a to the job
 | 
				
			||||||
    DLOG("Starting job kill timer");
 | 
					    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
 | 
					  // Increase refcount to stop the job from being freed before we have a
 | 
				
			||||||
  // chance to get the status.
 | 
					  // chance to get the status.
 | 
				
			||||||
  job->refcount++;
 | 
					  job->refcount++;
 | 
				
			||||||
  event_poll_until(ms,
 | 
					  LOOP_POLL_EVENTS_UNTIL(&loop, ms,
 | 
				
			||||||
      // Until...
 | 
					      // Until...
 | 
				
			||||||
      got_int ||                // interrupted by the user
 | 
					      got_int ||                // interrupted by the user
 | 
				
			||||||
      job->refcount == 1);  // job exited
 | 
					      job->refcount == 1);  // job exited
 | 
				
			||||||
@@ -259,9 +260,9 @@ int job_wait(Job *job, int ms) FUNC_ATTR_NONNULL_ALL
 | 
				
			|||||||
    if (ms == -1) {
 | 
					    if (ms == -1) {
 | 
				
			||||||
      // We can only return, if all streams/handles are closed and the job
 | 
					      // We can only return, if all streams/handles are closed and the job
 | 
				
			||||||
      // exited.
 | 
					      // exited.
 | 
				
			||||||
      event_poll_until(-1, job->refcount == 1);
 | 
					      LOOP_POLL_EVENTS_UNTIL(&loop, -1, job->refcount == 1);
 | 
				
			||||||
    } else {
 | 
					    } 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
 | 
					/// 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).
 | 
					/// 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;
 | 
					  Job *job;
 | 
				
			||||||
  uint64_t now = os_hrtime();
 | 
					  uint64_t now = os_hrtime();
 | 
				
			||||||
@@ -432,7 +433,7 @@ static void job_exited(Event event)
 | 
				
			|||||||
  process_close(job);
 | 
					  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 stat = 0;
 | 
				
			||||||
  int pid;
 | 
					  int pid;
 | 
				
			||||||
@@ -458,7 +459,8 @@ static void chld_handler(uv_signal_t *handle, int signum)
 | 
				
			|||||||
        // don't enqueue more events when exiting
 | 
					        // don't enqueue more events when exiting
 | 
				
			||||||
        process_close(job);
 | 
					        process_close(job);
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        event_push((Event) {.handler = job_exited, .data = job}, false);
 | 
					        loop_push_event(&loop,
 | 
				
			||||||
 | 
					            (Event) {.handler = job_exited, .data = job}, false);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "nvim/os/rstream_defs.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.h"
 | 
				
			||||||
#include "nvim/os/wstream_defs.h"
 | 
					#include "nvim/os/wstream_defs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <uv.h>
 | 
					#include <uv.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "nvim/event/time.h"
 | 
				
			||||||
#include "nvim/os/rstream_defs.h"
 | 
					#include "nvim/os/rstream_defs.h"
 | 
				
			||||||
#include "nvim/os/wstream_defs.h"
 | 
					#include "nvim/os/wstream_defs.h"
 | 
				
			||||||
#include "nvim/os/pipe_process.h"
 | 
					#include "nvim/os/pipe_process.h"
 | 
				
			||||||
@@ -43,7 +44,7 @@ struct job {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
extern Job *table[];
 | 
					extern Job *table[];
 | 
				
			||||||
extern size_t stop_requests;
 | 
					extern size_t stop_requests;
 | 
				
			||||||
extern uv_timer_t job_stop_timer;
 | 
					extern TimeWatcher job_stop_timer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline bool process_spawn(Job *job)
 | 
					static inline bool process_spawn(Job *job)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -95,7 +96,7 @@ static inline void job_exit_callback(Job *job)
 | 
				
			|||||||
  if (stop_requests && !--stop_requests) {
 | 
					  if (stop_requests && !--stop_requests) {
 | 
				
			||||||
    // Stop the timer if no more stop requests are pending
 | 
					    // Stop the timer if no more stop requests are pending
 | 
				
			||||||
    DLOG("Stopping job kill timer");
 | 
					    DLOG("Stopping job kill timer");
 | 
				
			||||||
    uv_timer_stop(&job_stop_timer);
 | 
					    time_watcher_stop(&job_stop_timer);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,8 @@
 | 
				
			|||||||
#include "nvim/os/job_private.h"
 | 
					#include "nvim/os/job_private.h"
 | 
				
			||||||
#include "nvim/os/pipe_process.h"
 | 
					#include "nvim/os/pipe_process.h"
 | 
				
			||||||
#include "nvim/memory.h"
 | 
					#include "nvim/memory.h"
 | 
				
			||||||
 | 
					#include "nvim/vim.h"
 | 
				
			||||||
 | 
					#include "nvim/globals.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
# include "os/pipe_process.c.generated.h"
 | 
					# 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);
 | 
					  handle_set_job((uv_handle_t *)&pipeproc->proc, job);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (job->opts.writable) {
 | 
					  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].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
 | 
				
			||||||
    pipeproc->stdio[0].data.stream = (uv_stream_t *)&pipeproc->proc_stdin;
 | 
					    pipeproc->stdio[0].data.stream = (uv_stream_t *)&pipeproc->proc_stdin;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (job->opts.stdout_cb) {
 | 
					  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].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
 | 
				
			||||||
    pipeproc->stdio[1].data.stream = (uv_stream_t *)&pipeproc->proc_stdout;
 | 
					    pipeproc->stdio[1].data.stream = (uv_stream_t *)&pipeproc->proc_stdout;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (job->opts.stderr_cb) {
 | 
					  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].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;
 | 
				
			||||||
    pipeproc->stdio[2].data.stream = (uv_stream_t *)&pipeproc->proc_stderr;
 | 
					    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;
 | 
					  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;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,6 +26,8 @@
 | 
				
			|||||||
#include "nvim/os/job_private.h"
 | 
					#include "nvim/os/job_private.h"
 | 
				
			||||||
#include "nvim/os/pty_process.h"
 | 
					#include "nvim/os/pty_process.h"
 | 
				
			||||||
#include "nvim/memory.h"
 | 
					#include "nvim/memory.h"
 | 
				
			||||||
 | 
					#include "nvim/vim.h"
 | 
				
			||||||
 | 
					#include "nvim/globals.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
# include "os/pty_process.c.generated.h"
 | 
					# 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;
 | 
					  ptyproc->tty_fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (job->opts.writable) {
 | 
					  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;
 | 
					    ptyproc->proc_stdin.data = NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (job->opts.stdout_cb) {
 | 
					  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;
 | 
					    ptyproc->proc_stdout.data = NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (job->opts.stderr_cb) {
 | 
					  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;
 | 
					    ptyproc->proc_stderr.data = NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					    // in chunks of rstream->buffer_size, giving time for other events to
 | 
				
			||||||
    // be processed between reads.
 | 
					    // be processed between reads.
 | 
				
			||||||
    rstream->fread_idle = xmalloc(sizeof(uv_idle_t));
 | 
					    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;
 | 
					    rstream->fread_idle->data = NULL;
 | 
				
			||||||
    handle_set_rstream((uv_handle_t *)rstream->fread_idle, rstream);
 | 
					    handle_set_rstream((uv_handle_t *)rstream->fread_idle, rstream);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
@@ -128,7 +128,7 @@ void rstream_set_file(RStream *rstream, uv_file file)
 | 
				
			|||||||
    assert(rstream->file_type == UV_NAMED_PIPE
 | 
					    assert(rstream->file_type == UV_NAMED_PIPE
 | 
				
			||||||
        || rstream->file_type == UV_TTY);
 | 
					        || rstream->file_type == UV_TTY);
 | 
				
			||||||
    rstream->stream = xmalloc(sizeof(uv_pipe_t));
 | 
					    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);
 | 
					    uv_pipe_open((uv_pipe_t *)rstream->stream, file);
 | 
				
			||||||
    rstream->stream->data = NULL;
 | 
					    rstream->stream->data = NULL;
 | 
				
			||||||
    handle_set_rstream((uv_handle_t *)rstream->stream, rstream);
 | 
					    handle_set_rstream((uv_handle_t *)rstream->stream, rstream);
 | 
				
			||||||
@@ -224,7 +224,7 @@ static void fread_idle_cb(uv_idle_t *handle)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // Synchronous read
 | 
					  // Synchronous read
 | 
				
			||||||
  uv_fs_read(
 | 
					  uv_fs_read(
 | 
				
			||||||
      uv_default_loop(),
 | 
					      &loop.uv,
 | 
				
			||||||
      &req,
 | 
					      &req,
 | 
				
			||||||
      rstream->fd,
 | 
					      rstream->fd,
 | 
				
			||||||
      &rstream->uvbuf,
 | 
					      &rstream->uvbuf,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,6 @@
 | 
				
			|||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <uv.h>
 | 
					#include <uv.h>
 | 
				
			||||||
#include "nvim/os/event_defs.h"
 | 
					 | 
				
			||||||
#include "nvim/os/rstream_defs.h"
 | 
					#include "nvim/os/rstream_defs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@
 | 
				
			|||||||
#include "nvim/ascii.h"
 | 
					#include "nvim/ascii.h"
 | 
				
			||||||
#include "nvim/lib/kvec.h"
 | 
					#include "nvim/lib/kvec.h"
 | 
				
			||||||
#include "nvim/log.h"
 | 
					#include "nvim/log.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/os/job.h"
 | 
					#include "nvim/os/job.h"
 | 
				
			||||||
#include "nvim/os/rstream.h"
 | 
					#include "nvim/os/rstream.h"
 | 
				
			||||||
#include "nvim/os/shell.h"
 | 
					#include "nvim/os/shell.h"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,13 @@
 | 
				
			|||||||
#include "nvim/memory.h"
 | 
					#include "nvim/memory.h"
 | 
				
			||||||
#include "nvim/misc1.h"
 | 
					#include "nvim/misc1.h"
 | 
				
			||||||
#include "nvim/misc2.h"
 | 
					#include "nvim/misc2.h"
 | 
				
			||||||
 | 
					#include "nvim/event/signal.h"
 | 
				
			||||||
#include "nvim/os/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
 | 
					#ifdef SIGPWR
 | 
				
			||||||
static uv_signal_t spwr;
 | 
					static SignalWatcher spwr;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool rejecting_deadly;
 | 
					static bool rejecting_deadly;
 | 
				
			||||||
@@ -27,40 +28,40 @@ static bool rejecting_deadly;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void signal_init(void)
 | 
					void signal_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &spipe);
 | 
					  signal_watcher_init(&loop, &spipe, NULL);
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &shup);
 | 
					  signal_watcher_init(&loop, &shup, NULL);
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &squit);
 | 
					  signal_watcher_init(&loop, &squit, NULL);
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &sterm);
 | 
					  signal_watcher_init(&loop, &sterm, NULL);
 | 
				
			||||||
  uv_signal_start(&spipe, signal_cb, SIGPIPE);
 | 
					  signal_watcher_start(&spipe, on_signal, SIGPIPE);
 | 
				
			||||||
  uv_signal_start(&shup, signal_cb, SIGHUP);
 | 
					  signal_watcher_start(&shup, on_signal, SIGHUP);
 | 
				
			||||||
  uv_signal_start(&squit, signal_cb, SIGQUIT);
 | 
					  signal_watcher_start(&squit, on_signal, SIGQUIT);
 | 
				
			||||||
  uv_signal_start(&sterm, signal_cb, SIGTERM);
 | 
					  signal_watcher_start(&sterm, on_signal, SIGTERM);
 | 
				
			||||||
#ifdef SIGPWR
 | 
					#ifdef SIGPWR
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &spwr);
 | 
					  signal_watcher_init(&loop, &spwr, NULL);
 | 
				
			||||||
  uv_signal_start(&spwr, signal_cb, SIGPWR);
 | 
					  signal_watcher_start(&spwr, on_signal, SIGPWR);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void signal_teardown(void)
 | 
					void signal_teardown(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  signal_stop();
 | 
					  signal_stop();
 | 
				
			||||||
  uv_close((uv_handle_t *)&spipe, NULL);
 | 
					  signal_watcher_close(&spipe, NULL);
 | 
				
			||||||
  uv_close((uv_handle_t *)&shup, NULL);
 | 
					  signal_watcher_close(&shup, NULL);
 | 
				
			||||||
  uv_close((uv_handle_t *)&squit, NULL);
 | 
					  signal_watcher_close(&squit, NULL);
 | 
				
			||||||
  uv_close((uv_handle_t *)&sterm, NULL);
 | 
					  signal_watcher_close(&sterm, NULL);
 | 
				
			||||||
#ifdef SIGPWR
 | 
					#ifdef SIGPWR
 | 
				
			||||||
  uv_close((uv_handle_t *)&spwr, NULL);
 | 
					  signal_watcher_close(&spwr, NULL);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void signal_stop(void)
 | 
					void signal_stop(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  uv_signal_stop(&spipe);
 | 
					  signal_watcher_stop(&spipe);
 | 
				
			||||||
  uv_signal_stop(&shup);
 | 
					  signal_watcher_stop(&shup);
 | 
				
			||||||
  uv_signal_stop(&squit);
 | 
					  signal_watcher_stop(&squit);
 | 
				
			||||||
  uv_signal_stop(&sterm);
 | 
					  signal_watcher_stop(&sterm);
 | 
				
			||||||
#ifdef SIGPWR
 | 
					#ifdef SIGPWR
 | 
				
			||||||
  uv_signal_stop(&spwr);
 | 
					  signal_watcher_stop(&spwr);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,10 +112,10 @@ static void deadly_signal(int signum)
 | 
				
			|||||||
  preserve_exit();
 | 
					  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);
 | 
					  assert(signum >= 0);
 | 
				
			||||||
  event_push((Event) {
 | 
					  loop_push_event(&loop, (Event) {
 | 
				
			||||||
    .handler = on_signal_event,
 | 
					    .handler = on_signal_event,
 | 
				
			||||||
    .data = (void *)(uintptr_t)signum
 | 
					    .data = (void *)(uintptr_t)signum
 | 
				
			||||||
  }, false);
 | 
					  }, false);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,6 @@
 | 
				
			|||||||
#ifndef NVIM_OS_SIGNAL_H
 | 
					#ifndef NVIM_OS_SIGNAL_H
 | 
				
			||||||
#define NVIM_OS_SIGNAL_H
 | 
					#define NVIM_OS_SIGNAL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "nvim/os/event_defs.h"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
# include "os/signal.h.generated.h"
 | 
					# include "os/signal.h.generated.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,7 +7,7 @@
 | 
				
			|||||||
#include <uv.h>
 | 
					#include <uv.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "nvim/os/time.h"
 | 
					#include "nvim/os/time.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/vim.h"
 | 
					#include "nvim/vim.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uv_mutex_t delay_mutex;
 | 
					static uv_mutex_t delay_mutex;
 | 
				
			||||||
@@ -43,7 +43,7 @@ void os_delay(uint64_t milliseconds, bool ignoreinput)
 | 
				
			|||||||
    if (milliseconds > INT_MAX) {
 | 
					    if (milliseconds > INT_MAX) {
 | 
				
			||||||
      milliseconds = INT_MAX;
 | 
					      milliseconds = INT_MAX;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    event_poll_until((int)milliseconds, got_int);
 | 
					    LOOP_POLL_EVENTS_UNTIL(&loop, (int)milliseconds, got_int);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    os_microdelay(milliseconds * 1000);
 | 
					    os_microdelay(milliseconds * 1000);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -103,7 +103,7 @@ void wstream_set_file(WStream *wstream, uv_file file)
 | 
				
			|||||||
  assert(uv_guess_handle(file) == UV_NAMED_PIPE ||
 | 
					  assert(uv_guess_handle(file) == UV_NAMED_PIPE ||
 | 
				
			||||||
         uv_guess_handle(file) == UV_TTY);
 | 
					         uv_guess_handle(file) == UV_TTY);
 | 
				
			||||||
  wstream->stream = xmalloc(sizeof(uv_pipe_t));
 | 
					  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);
 | 
					  uv_pipe_open((uv_pipe_t *)wstream->stream, file);
 | 
				
			||||||
  wstream->stream->data = NULL;
 | 
					  wstream->stream->data = NULL;
 | 
				
			||||||
  handle_set_wstream((uv_handle_t *)wstream->stream, wstream);
 | 
					  handle_set_wstream((uv_handle_t *)wstream->stream, wstream);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -47,13 +47,11 @@
 | 
				
			|||||||
#include "nvim/types.h"
 | 
					#include "nvim/types.h"
 | 
				
			||||||
#include "nvim/os/os.h"
 | 
					#include "nvim/os/os.h"
 | 
				
			||||||
#include "nvim/os/time.h"
 | 
					#include "nvim/os/time.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					 | 
				
			||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
#include "nvim/os/shell.h"
 | 
					#include "nvim/os/shell.h"
 | 
				
			||||||
#include "nvim/os/signal.h"
 | 
					#include "nvim/os/signal.h"
 | 
				
			||||||
#include "nvim/os/job.h"
 | 
					#include "nvim/os/job.h"
 | 
				
			||||||
#include "nvim/msgpack_rpc/helpers.h"
 | 
					#include "nvim/msgpack_rpc/helpers.h"
 | 
				
			||||||
#include "nvim/msgpack_rpc/defs.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef HAVE_STROPTS_H
 | 
					#ifdef HAVE_STROPTS_H
 | 
				
			||||||
# include <stropts.h>
 | 
					# include <stropts.h>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,7 +67,8 @@
 | 
				
			|||||||
#include "nvim/ex_cmds.h"
 | 
					#include "nvim/ex_cmds.h"
 | 
				
			||||||
#include "nvim/window.h"
 | 
					#include "nvim/window.h"
 | 
				
			||||||
#include "nvim/fileio.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"
 | 
					#include "nvim/api/private/helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
					#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
				
			||||||
@@ -80,7 +81,7 @@
 | 
				
			|||||||
// of data.
 | 
					// of data.
 | 
				
			||||||
#define REFRESH_DELAY 10
 | 
					#define REFRESH_DELAY 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static uv_timer_t refresh_timer;
 | 
					static TimeWatcher refresh_timer;
 | 
				
			||||||
static bool refresh_pending = false;
 | 
					static bool refresh_pending = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@@ -150,7 +151,7 @@ static VTermColor default_vt_bg_rgb;
 | 
				
			|||||||
void terminal_init(void)
 | 
					void terminal_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  invalidated_terminals = pmap_new(ptr_t)();
 | 
					  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
 | 
					  // initialize a rgb->color index map for cterm attributes(VTermScreenCell
 | 
				
			||||||
  // only has RGB information and we need color indexes for terminal UIs)
 | 
					  // only has RGB information and we need color indexes for terminal UIs)
 | 
				
			||||||
@@ -175,8 +176,8 @@ void terminal_init(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void terminal_teardown(void)
 | 
					void terminal_teardown(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  uv_timer_stop(&refresh_timer);
 | 
					  time_watcher_stop(&refresh_timer);
 | 
				
			||||||
  uv_close((uv_handle_t *)&refresh_timer, NULL);
 | 
					  time_watcher_close(&refresh_timer, NULL);
 | 
				
			||||||
  pmap_free(ptr_t)(invalidated_terminals);
 | 
					  pmap_free(ptr_t)(invalidated_terminals);
 | 
				
			||||||
  map_free(int, int)(color_indexes);
 | 
					  map_free(int, int)(color_indexes);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -353,13 +354,13 @@ void terminal_enter(bool process_deferred)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  while (term->buf == curbuf) {
 | 
					  while (term->buf == curbuf) {
 | 
				
			||||||
    if (process_deferred) {
 | 
					    if (process_deferred) {
 | 
				
			||||||
      event_enable_deferred();
 | 
					      loop_enable_deferred_events(&loop);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    c = safe_vgetc();
 | 
					    c = safe_vgetc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (process_deferred) {
 | 
					    if (process_deferred) {
 | 
				
			||||||
      event_disable_deferred();
 | 
					      loop_disable_deferred_events(&loop);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (c) {
 | 
					    switch (c) {
 | 
				
			||||||
@@ -380,7 +381,7 @@ void terminal_enter(bool process_deferred)
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case K_EVENT:
 | 
					      case K_EVENT:
 | 
				
			||||||
        event_process();
 | 
					        loop_process_event(&loop);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case Ctrl_N:
 | 
					      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);
 | 
					  pmap_put(ptr_t)(invalidated_terminals, term, NULL);
 | 
				
			||||||
  if (!refresh_pending) {
 | 
					  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;
 | 
					    refresh_pending = true;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// libuv timer callback. This will enqueue on_refresh to be processed as an
 | 
					// libuv timer callback. This will enqueue on_refresh to be processed as an
 | 
				
			||||||
// event.
 | 
					// 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;
 | 
					  refresh_pending = false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
#include "nvim/os/os.h"
 | 
					#include "nvim/os/os.h"
 | 
				
			||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
#include "nvim/os/rstream.h"
 | 
					#include "nvim/os/rstream.h"
 | 
				
			||||||
 | 
					#include "nvim/event/time.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PASTETOGGLE_KEY "<f37>"
 | 
					#define PASTETOGGLE_KEY "<f37>"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,7 +13,7 @@ struct term_input {
 | 
				
			|||||||
  int in_fd;
 | 
					  int in_fd;
 | 
				
			||||||
  bool paste_enabled;
 | 
					  bool paste_enabled;
 | 
				
			||||||
  TermKey *tk;
 | 
					  TermKey *tk;
 | 
				
			||||||
  uv_timer_t timer_handle;
 | 
					  TimeWatcher timer_handle;
 | 
				
			||||||
  RBuffer *read_buffer;
 | 
					  RBuffer *read_buffer;
 | 
				
			||||||
  RStream *read_stream;
 | 
					  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);
 | 
					  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)
 | 
					static int get_key_code_timeout(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -147,17 +148,16 @@ static void tk_getkeys(TermInput *input, bool force)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (ms > 0) {
 | 
					  if (ms > 0) {
 | 
				
			||||||
    // Stop the current timer if already running
 | 
					    // Stop the current timer if already running
 | 
				
			||||||
    uv_timer_stop(&input->timer_handle);
 | 
					    time_watcher_stop(&input->timer_handle);
 | 
				
			||||||
    uv_timer_start(&input->timer_handle, timer_cb, (uint32_t)ms, 0);
 | 
					    time_watcher_start(&input->timer_handle, timer_cb, (uint32_t)ms, 0);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    tk_getkeys(input, true);
 | 
					    tk_getkeys(input, true);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void timer_cb(TimeWatcher *watcher, void *data)
 | 
				
			||||||
static void timer_cb(uv_timer_t *handle)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  tk_getkeys(handle->data, true);
 | 
					  tk_getkeys(data, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool handle_bracketed_paste(TermInput *input)
 | 
					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_set_file(rv->read_stream, rv->in_fd);
 | 
				
			||||||
  rstream_start(rv->read_stream);
 | 
					  rstream_start(rv->read_stream);
 | 
				
			||||||
  // initialize a timer handle for handling ESC with libtermkey
 | 
					  // initialize a timer handle for handling ESC with libtermkey
 | 
				
			||||||
  uv_timer_init(uv_default_loop(), &rv->timer_handle);
 | 
					  time_watcher_init(&loop, &rv->timer_handle, rv);
 | 
				
			||||||
  rv->timer_handle.data = rv;
 | 
					 | 
				
			||||||
  // Set the pastetoggle option to a special key that will be sent when
 | 
					  // Set the pastetoggle option to a special key that will be sent when
 | 
				
			||||||
  // \e[20{0,1}~/ are received
 | 
					  // \e[20{0,1}~/ are received
 | 
				
			||||||
  Error err = ERROR_INIT;
 | 
					  Error err = ERROR_INIT;
 | 
				
			||||||
@@ -300,12 +299,13 @@ static TermInput *term_input_new(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void term_input_destroy(TermInput *input)
 | 
					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_stop(input->read_stream);
 | 
				
			||||||
  rstream_free(input->read_stream);
 | 
					  rstream_free(input->read_stream);
 | 
				
			||||||
  uv_close((uv_handle_t *)&input->timer_handle, NULL);
 | 
					 | 
				
			||||||
  termkey_destroy(input->tk);
 | 
					  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);
 | 
					  xfree(input);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,8 @@
 | 
				
			|||||||
#include "nvim/memory.h"
 | 
					#include "nvim/memory.h"
 | 
				
			||||||
#include "nvim/api/vim.h"
 | 
					#include "nvim/api/vim.h"
 | 
				
			||||||
#include "nvim/api/private/helpers.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/tui/tui.h"
 | 
				
			||||||
#include "nvim/strings.h"
 | 
					#include "nvim/strings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -43,7 +44,7 @@ typedef struct {
 | 
				
			|||||||
  uv_loop_t *write_loop;
 | 
					  uv_loop_t *write_loop;
 | 
				
			||||||
  unibi_term *ut;
 | 
					  unibi_term *ut;
 | 
				
			||||||
  uv_tty_t output_handle;
 | 
					  uv_tty_t output_handle;
 | 
				
			||||||
  uv_signal_t winch_handle;
 | 
					  SignalWatcher winch_handle;
 | 
				
			||||||
  Rect scroll_region;
 | 
					  Rect scroll_region;
 | 
				
			||||||
  kvec_t(Rect) invalid_regions;
 | 
					  kvec_t(Rect) invalid_regions;
 | 
				
			||||||
  int row, col;
 | 
					  int row, col;
 | 
				
			||||||
@@ -132,9 +133,8 @@ UI *tui_start(void)
 | 
				
			|||||||
  update_size(ui);
 | 
					  update_size(ui);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // listen for SIGWINCH
 | 
					  // listen for SIGWINCH
 | 
				
			||||||
  uv_signal_init(uv_default_loop(), &data->winch_handle);
 | 
					  signal_watcher_init(&loop, &data->winch_handle, ui);
 | 
				
			||||||
  uv_signal_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
 | 
					  signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
 | 
				
			||||||
  data->winch_handle.data = ui;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ui->stop = tui_stop;
 | 
					  ui->stop = tui_stop;
 | 
				
			||||||
  ui->rgb = os_getenv("NVIM_TUI_ENABLE_TRUE_COLOR") != NULL;
 | 
					  ui->rgb = os_getenv("NVIM_TUI_ENABLE_TRUE_COLOR") != NULL;
 | 
				
			||||||
@@ -172,8 +172,8 @@ static void tui_stop(UI *ui)
 | 
				
			|||||||
  TUIData *data = ui->data;
 | 
					  TUIData *data = ui->data;
 | 
				
			||||||
  // Destroy common stuff
 | 
					  // Destroy common stuff
 | 
				
			||||||
  kv_destroy(data->invalid_regions);
 | 
					  kv_destroy(data->invalid_regions);
 | 
				
			||||||
  uv_signal_stop(&data->winch_handle);
 | 
					  signal_watcher_stop(&data->winch_handle);
 | 
				
			||||||
  uv_close((uv_handle_t *)&data->winch_handle, NULL);
 | 
					  signal_watcher_close(&data->winch_handle, NULL);
 | 
				
			||||||
  // Destroy input stuff
 | 
					  // Destroy input stuff
 | 
				
			||||||
  term_input_destroy(data->input);
 | 
					  term_input_destroy(data->input);
 | 
				
			||||||
  // Destroy output stuff
 | 
					  // Destroy output stuff
 | 
				
			||||||
@@ -207,12 +207,12 @@ static void try_resize(Event ev)
 | 
				
			|||||||
  ui_refresh();
 | 
					  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
 | 
					  // Queue the event because resizing can result in recursive event_poll calls
 | 
				
			||||||
  // FIXME(blueyed): TUI does not resize properly when not deferred. Why? #2322
 | 
					  // FIXME(blueyed): TUI does not resize properly when not deferred. Why? #2322
 | 
				
			||||||
  event_push((Event) {
 | 
					  loop_push_event(&loop, (Event) {
 | 
				
			||||||
    .data = handle->data,
 | 
					    .data = data,
 | 
				
			||||||
    .handler = try_resize
 | 
					    .handler = try_resize
 | 
				
			||||||
  }, true);
 | 
					  }, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,7 +23,7 @@
 | 
				
			|||||||
#include "nvim/normal.h"
 | 
					#include "nvim/normal.h"
 | 
				
			||||||
#include "nvim/option.h"
 | 
					#include "nvim/option.h"
 | 
				
			||||||
#include "nvim/os_unix.h"
 | 
					#include "nvim/os_unix.h"
 | 
				
			||||||
#include "nvim/os/event.h"
 | 
					#include "nvim/event/loop.h"
 | 
				
			||||||
#include "nvim/os/time.h"
 | 
					#include "nvim/os/time.h"
 | 
				
			||||||
#include "nvim/os/input.h"
 | 
					#include "nvim/os/input.h"
 | 
				
			||||||
#include "nvim/os/signal.h"
 | 
					#include "nvim/os/signal.h"
 | 
				
			||||||
@@ -216,7 +216,7 @@ void ui_detach(UI *ui)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  ui_count--;
 | 
					  ui_count--;
 | 
				
			||||||
  // schedule a refresh
 | 
					  // schedule a refresh
 | 
				
			||||||
  event_push((Event) { .handler = refresh }, false);
 | 
					  loop_push_event(&loop, (Event) { .handler = refresh }, false);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ui_clear(void)
 | 
					void ui_clear(void)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,7 +19,7 @@ require('bit')
 | 
				
			|||||||
cimport('unistd.h')
 | 
					cimport('unistd.h')
 | 
				
			||||||
cimport('./src/nvim/os/shell.h')
 | 
					cimport('./src/nvim/os/shell.h')
 | 
				
			||||||
cimport('./src/nvim/option_defs.h')
 | 
					cimport('./src/nvim/option_defs.h')
 | 
				
			||||||
cimport('./src/nvim/os/event.h')
 | 
					cimport('./src/nvim/main.h')
 | 
				
			||||||
cimport('./src/nvim/fileio.h')
 | 
					cimport('./src/nvim/fileio.h')
 | 
				
			||||||
local fs = cimport('./src/nvim/os/os.h')
 | 
					local fs = cimport('./src/nvim/os/os.h')
 | 
				
			||||||
cppimport('sys/stat.h')
 | 
					cppimport('sys/stat.h')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ local helpers = require('test.unit.helpers')
 | 
				
			|||||||
local shell = helpers.cimport(
 | 
					local shell = helpers.cimport(
 | 
				
			||||||
  './src/nvim/os/shell.h',
 | 
					  './src/nvim/os/shell.h',
 | 
				
			||||||
  './src/nvim/option_defs.h',
 | 
					  './src/nvim/option_defs.h',
 | 
				
			||||||
  './src/nvim/os/event.h',
 | 
					  './src/nvim/main.h',
 | 
				
			||||||
  './src/nvim/misc1.h'
 | 
					  './src/nvim/misc1.h'
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
local ffi, eq, neq = helpers.ffi, helpers.eq, helpers.neq
 | 
					local ffi, eq, neq = helpers.ffi, helpers.eq, helpers.neq
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user