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:
Thiago de Arruda 2015-07-24 10:38:35 -03:00
parent ccdeb91e12
commit 3f5af6c1c4
7 changed files with 39 additions and 63 deletions

View File

@ -601,11 +601,11 @@ edit (
* Get a character for Insert mode. Ignore K_IGNORE.
*/
lastc = c; /* remember previous char for CTRL-D */
loop_enable_deferred_events(&loop);
input_enable_events();
do {
c = safe_vgetc();
} while (c == K_IGNORE);
loop_disable_deferred_events(&loop);
input_disable_events();
if (c == K_EVENT) {
c = lastc;

View File

@ -20,6 +20,7 @@ void loop_init(Loop *loop, void *data)
loop->children_stop_requests = 0;
uv_signal_init(&loop->uv, &loop->children_watcher);
uv_timer_init(&loop->uv, &loop->children_kill_timer);
uv_timer_init(&loop->uv, &loop->poll_timer);
}
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
}
bool wait = true;
uv_timer_t timer;
uv_run_mode mode = UV_RUN_ONCE;
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);
uv_timer_start(&loop->poll_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;
mode = UV_RUN_NOWAIT;
}
if (wait) {
loop_run_once(loop);
} else {
loop_run_nowait(loop);
}
uv_run(&loop->uv, 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_run_nowait(loop);
uv_timer_stop(&loop->poll_timer);
}
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)
@ -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
// returns(user hits a key for example). To avoid this scenario, we call
// uv_stop when a event is enqueued.
loop_stop(loop);
uv_stop(&loop->uv);
kl_push(Event, deferred ? loop->deferred_events : loop->immediate_events,
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)
{
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
uv_close((uv_handle_t *)&loop->children_kill_timer, NULL);
uv_close((uv_handle_t *)&loop->poll_timer, NULL);
do {
uv_run(&loop->uv, UV_RUN_DEFAULT);
} while (uv_loop_close(&loop->uv));

View File

@ -25,10 +25,9 @@ KLIST_INIT(Event, Event, _noop)
typedef struct loop {
uv_loop_t uv;
klist_t(Event) *deferred_events, *immediate_events;
int deferred_events_allowed;
klist_t(WatcherPtr) *children;
uv_signal_t children_watcher;
uv_timer_t children_kill_timer;
uv_timer_t children_kill_timer, poll_timer;
size_t children_stop_requests;
} Loop;

View File

@ -62,6 +62,7 @@
#include "nvim/tag.h"
#include "nvim/window.h"
#include "nvim/ui.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/event/loop.h"
@ -298,11 +299,11 @@ getcmdline (
/* Get a character. Ignore K_IGNORE, it should not do anything, such
* as stop completion. */
loop_enable_deferred_events(&loop);
input_enable_events();
do {
c = safe_vgetc();
} while (c == K_IGNORE);
loop_disable_deferred_events(&loop);
input_disable_events();
if (c == K_EVENT) {
loop_process_event(&loop);

View File

@ -63,6 +63,7 @@
#include "nvim/window.h"
#include "nvim/event/loop.h"
#include "nvim/os/time.h"
#include "nvim/os/input.h"
/*
* The Visual area is remembered for reselection.
@ -487,9 +488,9 @@ normal_cmd (
/*
* Get the command character from the user.
*/
loop_enable_deferred_events(&loop);
input_enable_events();
c = safe_vgetc();
loop_disable_deferred_events(&loop);
input_disable_events();
if (c == K_EVENT) {
loop_process_event(&loop);

View File

@ -33,6 +33,7 @@ static Stream read_stream = {.closed = true};
static RBuffer *input_buffer = NULL;
static bool input_eof = false;
static int global_fd = 0;
static int events_enabled = 0;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# 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);
}
// If there are deferred events, return the keys directly
if (loop_has_deferred_events(&loop)) {
// If there are events, return the keys directly
if (pending_events()) {
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.
///
/// @param fd File descriptor.
@ -358,7 +369,7 @@ static bool input_ready(void)
{
return typebuf_was_filled || // API call filled typeahead
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.
@ -369,3 +380,8 @@ static void read_error_exit(void)
STRCPY(IObuff, _("Vim: Error reading input, exiting...\n"));
preserve_exit();
}
static bool pending_events(void)
{
return events_enabled && !kl_empty(loop.deferred_events);
}

View File

@ -69,6 +69,7 @@
#include "nvim/fileio.h"
#include "nvim/event/loop.h"
#include "nvim/event/time.h"
#include "nvim/os/input.h"
#include "nvim/api/private/helpers.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@ -354,13 +355,13 @@ void terminal_enter(bool process_deferred)
while (term->buf == curbuf) {
if (process_deferred) {
loop_enable_deferred_events(&loop);
input_enable_events();
}
c = safe_vgetc();
if (process_deferred) {
loop_disable_deferred_events(&loop);
input_disable_events();
}
switch (c) {