mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
event.c: Simplify timer use in event_poll()
event_poll() always leaves the libuv I/O loop after one iteration. The duration for how long the loop polls for I/O is given by the shortest timeout of all active timers. Is no timer active, I/O is/could be polled indefinitely. To make sure our timer is still active when I/O polling begins, a prepare handle is used to start the timer right before the polling. But by only using a timer that restarts after its timeout was reached, we also can assure that polling is done with (nearly) the same finite timeout. For a short explanation how the I/O loop is working, see http://docs.libuv.org/en/latest/design.html#the-i-o-loop.
This commit is contained in:
parent
95db8df682
commit
5f98c32725
@ -28,12 +28,6 @@
|
|||||||
#define _destroy_event(x) // do nothing
|
#define _destroy_event(x) // do nothing
|
||||||
KLIST_INIT(Event, Event, _destroy_event)
|
KLIST_INIT(Event, Event, _destroy_event)
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool timed_out;
|
|
||||||
int ms;
|
|
||||||
uv_timer_t *timer;
|
|
||||||
} TimerData;
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "os/event.c.generated.h"
|
# include "os/event.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@ -107,19 +101,12 @@ void event_poll(int ms)
|
|||||||
|
|
||||||
uv_run_mode run_mode = UV_RUN_ONCE;
|
uv_run_mode run_mode = UV_RUN_ONCE;
|
||||||
uv_timer_t timer;
|
uv_timer_t timer;
|
||||||
uv_prepare_t timer_prepare;
|
|
||||||
TimerData timer_data = {.ms = ms, .timed_out = false, .timer = &timer};
|
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
uv_timer_init(uv_default_loop(), &timer);
|
uv_timer_init(uv_default_loop(), &timer);
|
||||||
// This prepare handle that actually starts the timer
|
// Use a repeating timeout of ms milliseconds to make sure
|
||||||
uv_prepare_init(uv_default_loop(), &timer_prepare);
|
// we do not block indefinitely for I/O.
|
||||||
// Timeout passed as argument to the timer
|
uv_timer_start(&timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
||||||
timer.data = &timer_data;
|
|
||||||
// We only start the timer after the loop is running, for that we
|
|
||||||
// use a prepare handle(pass the interval as data to it)
|
|
||||||
timer_prepare.data = &timer_data;
|
|
||||||
uv_prepare_start(&timer_prepare, timer_prepare_cb);
|
|
||||||
} 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.
|
||||||
@ -129,12 +116,10 @@ void event_poll(int ms)
|
|||||||
loop(run_mode);
|
loop(run_mode);
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
// Ensure the timer-related handles are closed and run the event loop
|
// Ensure the timer handle is closed and run the event loop
|
||||||
// once more to let libuv perform it's cleanup
|
// once more to let libuv perform it's cleanup
|
||||||
uv_timer_stop(&timer);
|
uv_timer_stop(&timer);
|
||||||
uv_prepare_stop(&timer_prepare);
|
|
||||||
uv_close((uv_handle_t *)&timer, NULL);
|
uv_close((uv_handle_t *)&timer, NULL);
|
||||||
uv_close((uv_handle_t *)&timer_prepare, NULL);
|
|
||||||
loop(UV_RUN_NOWAIT);
|
loop(UV_RUN_NOWAIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,19 +168,8 @@ static void process_events_from(klist_t(Event) *queue)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a flag in the `event_poll` loop for signaling of a timeout
|
|
||||||
static void timer_cb(uv_timer_t *handle)
|
static void timer_cb(uv_timer_t *handle)
|
||||||
{
|
{
|
||||||
TimerData *data = handle->data;
|
|
||||||
data->timed_out = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void timer_prepare_cb(uv_prepare_t *handle)
|
|
||||||
{
|
|
||||||
TimerData *data = handle->data;
|
|
||||||
assert(data->ms > 0);
|
|
||||||
uv_timer_start(data->timer, timer_cb, (uint32_t)data->ms, 0);
|
|
||||||
uv_prepare_stop(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loop(uv_run_mode run_mode)
|
static void loop(uv_run_mode run_mode)
|
||||||
|
Loading…
Reference in New Issue
Block a user