event: Refactor async event processing

- Improve the implementation of deferred/immediate events.
- Use the new queue module to change how/when events are queued/processed by
  giving a private queue to each emitter.
- Immediate events(which only exist to break uv_run recursion) are now
  represented in the `loop->fast_events` queue.
- Events pushed to child queues are propagated to the event loop main queue and
  processed as K_EVENT keys.
This commit is contained in:
Thiago de Arruda
2015-08-07 22:54:02 -03:00
parent a6e0d35d2d
commit 502aee690c
28 changed files with 216 additions and 211 deletions

View File

@@ -1,3 +1,4 @@
#include <stdarg.h>
#include <stdint.h>
#include <uv.h>
@@ -9,15 +10,20 @@
# include "event/loop.c.generated.h"
#endif
typedef struct idle_event {
uv_idle_t idle;
Event event;
} IdleEvent;
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);
loop->children = kl_init(WatcherPtr);
loop->children_stop_requests = 0;
loop->events = queue_new_parent(on_put, loop);
loop->fast_events = queue_new_child(loop->events);
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);
@@ -50,29 +56,20 @@ void loop_poll_events(Loop *loop, int ms)
}
recursive--; // Can re-enter uv_run now
process_events_from(loop->immediate_events);
queue_process_events(loop->fast_events);
}
// Queue an event
void loop_push_event(Loop *loop, Event event, bool deferred)
static void on_put(Queue *queue, void *data)
{
Loop *loop = data;
// 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(&loop->uv);
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_close(Loop *loop)
{
uv_close((uv_handle_t *)&loop->children_watcher, NULL);
@@ -83,20 +80,6 @@ void loop_close(Loop *loop)
} 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)
{
}