Define special key for asynchronous events

K_EVENT/KE_EVENT are used to signal any loop that reads user input(scattered
across normal.c edit.c , ex_getln.c and message.c) of asynchronous events that
were not initiated by the user.

Representing non-user asynchronous events as special keys has the following
advantages:

- We reuse the normal vim redrawing code. As far as the rest of the code in
  edit.c/normal.c is concerned, it's just the user pressing another key.
- Assume less about vim tolerance for "out-of-band" modifications to its
  internal state.
- We still have a very complex codebase and it's hard to predict what bugs may
  be introduced by these changes. With this we implement asynchronicity in a way
  that will be more "natural" to the editor and has less chance of causing
  unpredictable behavior.

As the code is refactored, we will be able to treat user input as an 'event
type' and not the other way around(With this we are treating arbitrary events as
a special case of user input).
This commit is contained in:
Thiago de Arruda
2014-04-07 16:37:14 -03:00
parent 1fc7d6a0c5
commit fe38baed38
10 changed files with 86 additions and 78 deletions

View File

@@ -20,8 +20,6 @@ KLIST_INIT(Event, Event, _destroy_event)
static klist_t(Event) *event_queue;
static uv_timer_t timer;
static uv_prepare_t timer_prepare;
static bool poll_uv_loop(int ms);
static void process_all_events(void);
static void timer_cb(uv_timer_t *handle, int);
static void timer_prepare_cb(uv_prepare_t *, int);
@@ -42,66 +40,8 @@ void event_init()
uv_prepare_init(uv_default_loop(), &timer_prepare);
}
bool event_poll(int32_t ms)
{
int64_t remaining = ms;
uint64_t end;
bool result;
if (ms > 0) {
// Calculate end time in nanoseconds
end = uv_hrtime() + ms * 1e6;
}
for (;;) {
result = poll_uv_loop((int32_t)remaining);
// Process queued events
process_all_events();
if (ms > 0) {
// Calculate remaining time in milliseconds
remaining = (end - uv_hrtime()) / 1e6;
}
if (input_ready() || got_int) {
// Bail out if we have pending input
return true;
}
if (!result || (ms >= 0 && remaining <= 0)) {
// Or if we timed out
return false;
}
}
}
// Push an event to the queue
void event_push(Event event)
{
*kl_pushp(Event, event_queue) = event;
}
// Runs the appropriate action for each queued event
static void process_all_events()
{
Event event;
while (kl_shift(Event, event_queue, &event) == 0) {
switch (event.type) {
case kEventSignal:
signal_handle(event);
break;
case kEventJobActivity:
job_handle(event);
break;
default:
abort();
}
}
}
// Wait for some event
static bool poll_uv_loop(int32_t ms)
bool event_poll(int32_t ms)
{
bool timed_out;
uv_run_mode run_mode = UV_RUN_ONCE;
@@ -145,7 +85,37 @@ static bool poll_uv_loop(int32_t ms)
uv_timer_stop(&timer);
}
return input_ready() || !kl_empty(event_queue);
return input_ready() || event_is_pending();
}
bool event_is_pending()
{
return !kl_empty(event_queue);
}
// Push an event to the queue
void event_push(Event event)
{
*kl_pushp(Event, event_queue) = event;
}
// Runs the appropriate action for each queued event
void event_process()
{
Event event;
while (kl_shift(Event, event_queue, &event) == 0) {
switch (event.type) {
case kEventSignal:
signal_handle(event);
break;
case kEventJobActivity:
job_handle(event);
break;
default:
abort();
}
}
}
// Set a flag in the `event_poll` loop for signaling of a timeout