Reimplement the event queue in event.c using klist.h

- Add a new macro to klist.h: kl_empty()

   The whole point of abstract data structures is to avoid reimplementing
   common actions. The emptiness test seems to be such an action.

 - Add a new function attribute to func_attr.h: FUNC_ATTR_UNUSED

   Some of the many functions created by the macros in klist.h may end up not
   being used. Unused functions cause compilation errors as we compile with
   -Werror. To mark those functions as possibly unused we can use the
   FUNC_ATTR_UNUSED now.

 - Pass `Event` by value

   `Event` is such a small struct that I don't think we should allocate heap space
   and pass it by reference. Let's use the stack and memory cache in our favor
   passing it by value.
This commit is contained in:
Felipe Oliveira Carvalho
2014-04-05 23:37:39 -03:00
committed by Thiago de Arruda
parent fac85c1724
commit 967fb1aca6
6 changed files with 34 additions and 48 deletions

View File

@@ -4,6 +4,7 @@
#include <uv.h>
#include "lib/klist.h"
#include "os/event.h"
#include "os/input.h"
#include "os/signal.h"
@@ -11,22 +12,22 @@
#include "memory.h"
#include "misc2.h"
typedef struct EventNode {
Event *event;
struct EventNode *next;
} EventNode;
// event.data will be cleaned up after the event is processed
#define _destroy_event(x) // do nothing
KLIST_INIT(Event, Event, _destroy_event)
static EventNode *head, *tail;
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 bool has_pending_events(void);
static void timer_cb(uv_timer_t *handle, int);
static void timer_prepare_cb(uv_prepare_t *, int);
void event_init()
{
// Initialize the event queue
event_queue = kl_init(Event);
// Initialize input events
input_init();
// Timer to wake the event loop if a timeout argument is passed to
@@ -72,50 +73,27 @@ bool event_poll(int32_t ms)
}
// Push an event to the queue
void event_push(Event *event)
void event_push(Event event)
{
EventNode *node = (EventNode *)xmalloc(sizeof(EventNode));
node->event = event;
node->next = NULL;
if (head == NULL) {
head = node;
} else {
tail->next = node;
}
tail = node;
*kl_pushp(Event, event_queue) = event;
}
// Runs the appropriate action for each queued event
static void process_all_events()
{
EventNode *next;
Event *event;
Event event;
while (has_pending_events()) {
next = head->next;
event = head->event;
free(head);
head = next;
switch (event->type) {
while (kl_shift(Event, event_queue, &event) == 0) {
switch (event.type) {
case kEventSignal:
signal_handle(event);
break;
default:
abort();
}
}
}
// Checks if there are queued events
bool has_pending_events()
{
return head != NULL;
}
// Wait for some event
static bool poll_uv_loop(int32_t ms)
{
@@ -150,7 +128,7 @@ static bool poll_uv_loop(int32_t ms)
} while (
// Continue running if ...
!input_ready() && // we have no input
!has_pending_events() && // no events are waiting to be processed
kl_empty(event_queue) && // no events are waiting to be processed
run_mode != UV_RUN_NOWAIT && // ms != 0
!timed_out // we didn't get a timeout
);
@@ -162,7 +140,7 @@ static bool poll_uv_loop(int32_t ms)
uv_timer_stop(&timer);
}
return input_ready() || has_pending_events();
return input_ready() || !kl_empty(event_queue);
}
// Set a flag in the `event_poll` loop for signaling of a timeout