mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
loop: Simplify loop.c and move some code to input.c
- Declare poll timer in Loop structure instead of a loop_poll_events local variable. - Move deferred event management to input.c
This commit is contained in:
parent
ccdeb91e12
commit
3f5af6c1c4
@ -601,11 +601,11 @@ 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 */
|
||||||
loop_enable_deferred_events(&loop);
|
input_enable_events();
|
||||||
do {
|
do {
|
||||||
c = safe_vgetc();
|
c = safe_vgetc();
|
||||||
} while (c == K_IGNORE);
|
} while (c == K_IGNORE);
|
||||||
loop_disable_deferred_events(&loop);
|
input_disable_events();
|
||||||
|
|
||||||
if (c == K_EVENT) {
|
if (c == K_EVENT) {
|
||||||
c = lastc;
|
c = lastc;
|
||||||
|
@ -20,6 +20,7 @@ void loop_init(Loop *loop, void *data)
|
|||||||
loop->children_stop_requests = 0;
|
loop->children_stop_requests = 0;
|
||||||
uv_signal_init(&loop->uv, &loop->children_watcher);
|
uv_signal_init(&loop->uv, &loop->children_watcher);
|
||||||
uv_timer_init(&loop->uv, &loop->children_kill_timer);
|
uv_timer_init(&loop->uv, &loop->children_kill_timer);
|
||||||
|
uv_timer_init(&loop->uv, &loop->poll_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop_poll_events(Loop *loop, int ms)
|
void loop_poll_events(Loop *loop, int ms)
|
||||||
@ -30,52 +31,28 @@ void loop_poll_events(Loop *loop, int ms)
|
|||||||
abort(); // Should not re-enter uv_run
|
abort(); // Should not re-enter uv_run
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wait = true;
|
uv_run_mode mode = UV_RUN_ONCE;
|
||||||
uv_timer_t timer;
|
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
uv_timer_init(&loop->uv, &timer);
|
|
||||||
// Use a repeating timeout of ms milliseconds to make sure
|
// Use a repeating timeout of ms milliseconds to make sure
|
||||||
// we do not block indefinitely for I/O.
|
// we do not block indefinitely for I/O.
|
||||||
uv_timer_start(&timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
||||||
} else if (ms == 0) {
|
} else if (ms == 0) {
|
||||||
// For ms == 0, we need to do a non-blocking event poll by
|
// For ms == 0, we need to do a non-blocking event poll by
|
||||||
// setting the run mode to UV_RUN_NOWAIT.
|
// setting the run mode to UV_RUN_NOWAIT.
|
||||||
wait = false;
|
mode = UV_RUN_NOWAIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait) {
|
uv_run(&loop->uv, mode);
|
||||||
loop_run_once(loop);
|
|
||||||
} else {
|
|
||||||
loop_run_nowait(loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
// Ensure the timer handle is closed and run the event loop
|
uv_timer_stop(&loop->poll_timer);
|
||||||
// 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
|
recursive--; // Can re-enter uv_run now
|
||||||
process_events_from(loop->immediate_events);
|
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
|
// Queue an event
|
||||||
void loop_push_event(Loop *loop, Event event, bool deferred)
|
void loop_push_event(Loop *loop, Event event, bool deferred)
|
||||||
@ -85,7 +62,7 @@ void loop_push_event(Loop *loop, Event event, bool deferred)
|
|||||||
// of the queues, the event would only be processed after the poll
|
// 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
|
// returns(user hits a key for example). To avoid this scenario, we call
|
||||||
// uv_stop when a event is enqueued.
|
// uv_stop when a event is enqueued.
|
||||||
loop_stop(loop);
|
uv_stop(&loop->uv);
|
||||||
kl_push(Event, deferred ? loop->deferred_events : loop->immediate_events,
|
kl_push(Event, deferred ? loop->deferred_events : loop->immediate_events,
|
||||||
event);
|
event);
|
||||||
}
|
}
|
||||||
@ -96,30 +73,11 @@ void loop_process_event(Loop *loop)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
void loop_close(Loop *loop)
|
||||||
{
|
{
|
||||||
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
|
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
|
||||||
uv_close((uv_handle_t *)&loop->children_kill_timer, NULL);
|
uv_close((uv_handle_t *)&loop->children_kill_timer, NULL);
|
||||||
|
uv_close((uv_handle_t *)&loop->poll_timer, NULL);
|
||||||
do {
|
do {
|
||||||
uv_run(&loop->uv, UV_RUN_DEFAULT);
|
uv_run(&loop->uv, UV_RUN_DEFAULT);
|
||||||
} while (uv_loop_close(&loop->uv));
|
} while (uv_loop_close(&loop->uv));
|
||||||
|
@ -25,10 +25,9 @@ KLIST_INIT(Event, Event, _noop)
|
|||||||
typedef struct loop {
|
typedef struct loop {
|
||||||
uv_loop_t uv;
|
uv_loop_t uv;
|
||||||
klist_t(Event) *deferred_events, *immediate_events;
|
klist_t(Event) *deferred_events, *immediate_events;
|
||||||
int deferred_events_allowed;
|
|
||||||
klist_t(WatcherPtr) *children;
|
klist_t(WatcherPtr) *children;
|
||||||
uv_signal_t children_watcher;
|
uv_signal_t children_watcher;
|
||||||
uv_timer_t children_kill_timer;
|
uv_timer_t children_kill_timer, poll_timer;
|
||||||
size_t children_stop_requests;
|
size_t children_stop_requests;
|
||||||
} Loop;
|
} Loop;
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
#include "nvim/tag.h"
|
#include "nvim/tag.h"
|
||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
#include "nvim/event/loop.h"
|
#include "nvim/event/loop.h"
|
||||||
|
|
||||||
@ -298,11 +299,11 @@ 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. */
|
||||||
loop_enable_deferred_events(&loop);
|
input_enable_events();
|
||||||
do {
|
do {
|
||||||
c = safe_vgetc();
|
c = safe_vgetc();
|
||||||
} while (c == K_IGNORE);
|
} while (c == K_IGNORE);
|
||||||
loop_disable_deferred_events(&loop);
|
input_disable_events();
|
||||||
|
|
||||||
if (c == K_EVENT) {
|
if (c == K_EVENT) {
|
||||||
loop_process_event(&loop);
|
loop_process_event(&loop);
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
#include "nvim/event/loop.h"
|
#include "nvim/event/loop.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
|
#include "nvim/os/input.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Visual area is remembered for reselection.
|
* The Visual area is remembered for reselection.
|
||||||
@ -487,9 +488,9 @@ normal_cmd (
|
|||||||
/*
|
/*
|
||||||
* Get the command character from the user.
|
* Get the command character from the user.
|
||||||
*/
|
*/
|
||||||
loop_enable_deferred_events(&loop);
|
input_enable_events();
|
||||||
c = safe_vgetc();
|
c = safe_vgetc();
|
||||||
loop_disable_deferred_events(&loop);
|
input_disable_events();
|
||||||
|
|
||||||
if (c == K_EVENT) {
|
if (c == K_EVENT) {
|
||||||
loop_process_event(&loop);
|
loop_process_event(&loop);
|
||||||
|
@ -33,6 +33,7 @@ static Stream read_stream = {.closed = true};
|
|||||||
static RBuffer *input_buffer = NULL;
|
static RBuffer *input_buffer = NULL;
|
||||||
static bool input_eof = false;
|
static bool input_eof = false;
|
||||||
static int global_fd = 0;
|
static int global_fd = 0;
|
||||||
|
static int events_enabled = 0;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "os/input.c.generated.h"
|
# include "os/input.c.generated.h"
|
||||||
@ -110,8 +111,8 @@ int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt)
|
|||||||
return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
|
return (int)rbuffer_read(input_buffer, (char *)buf, (size_t)maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are deferred events, return the keys directly
|
// If there are events, return the keys directly
|
||||||
if (loop_has_deferred_events(&loop)) {
|
if (pending_events()) {
|
||||||
return push_event_key(buf, maxlen);
|
return push_event_key(buf, maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,6 +137,16 @@ void os_breakcheck(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void input_enable_events(void)
|
||||||
|
{
|
||||||
|
events_enabled++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_disable_events(void)
|
||||||
|
{
|
||||||
|
events_enabled--;
|
||||||
|
}
|
||||||
|
|
||||||
/// Test whether a file descriptor refers to a terminal.
|
/// Test whether a file descriptor refers to a terminal.
|
||||||
///
|
///
|
||||||
/// @param fd File descriptor.
|
/// @param fd File descriptor.
|
||||||
@ -358,7 +369,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
|
||||||
loop_has_deferred_events(&loop); // Events must be processed
|
pending_events(); // Events must be processed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exit because of an input read error.
|
// Exit because of an input read error.
|
||||||
@ -369,3 +380,8 @@ static void read_error_exit(void)
|
|||||||
STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
|
STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
|
||||||
preserve_exit();
|
preserve_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool pending_events(void)
|
||||||
|
{
|
||||||
|
return events_enabled && !kl_empty(loop.deferred_events);
|
||||||
|
}
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/event/loop.h"
|
#include "nvim/event/loop.h"
|
||||||
#include "nvim/event/time.h"
|
#include "nvim/event/time.h"
|
||||||
|
#include "nvim/os/input.h"
|
||||||
#include "nvim/api/private/helpers.h"
|
#include "nvim/api/private/helpers.h"
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
@ -354,13 +355,13 @@ void terminal_enter(bool process_deferred)
|
|||||||
|
|
||||||
while (term->buf == curbuf) {
|
while (term->buf == curbuf) {
|
||||||
if (process_deferred) {
|
if (process_deferred) {
|
||||||
loop_enable_deferred_events(&loop);
|
input_enable_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
c = safe_vgetc();
|
c = safe_vgetc();
|
||||||
|
|
||||||
if (process_deferred) {
|
if (process_deferred) {
|
||||||
loop_disable_deferred_events(&loop);
|
input_disable_events();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
Loading…
Reference in New Issue
Block a user