[WIP] Event loop refactoring (#19)

* task queue tests and extensions

* event loop refactor

* fix formating
This commit is contained in:
Philipp Moritz
2016-09-23 22:53:58 -07:00
committed by Robert Nishihara
parent e1b8711a01
commit 7907992609
18 changed files with 1610 additions and 348 deletions
+42 -78
View File
@@ -1,98 +1,62 @@
#include "event_loop.h"
#include <assert.h>
#include "common.h"
#include <errno.h>
UT_icd item_icd = {sizeof(event_loop_item), NULL, NULL, NULL};
UT_icd poll_icd = {sizeof(struct pollfd), NULL, NULL, NULL};
#define INITIAL_EVENT_LOOP_SIZE 1024
/* Initializes the event loop.
* This function needs to be called before any other event loop function. */
void event_loop_init(event_loop *loop) {
utarray_new(loop->items, &item_icd);
utarray_new(loop->waiting, &poll_icd);
event_loop *event_loop_create() {
return aeCreateEventLoop(INITIAL_EVENT_LOOP_SIZE);
}
/* Free the space associated to the event loop.
* Does not free the event_loop datastructure itself. */
void event_loop_free(event_loop *loop) {
utarray_free(loop->items);
utarray_free(loop->waiting);
}
/* Add a new file descriptor fd to the event loop.
* This function sets a user defined type and id for the file descriptor
* which can be queried using event_loop_type and event_loop_id. The parameter
* events is the same as in http://linux.die.net/man/2/poll.
* Returns the index of the item in the event loop. */
int64_t event_loop_attach(event_loop *loop,
int type,
void *data,
int fd,
int events) {
assert(utarray_len(loop->items) == utarray_len(loop->waiting));
int64_t index = utarray_len(loop->items);
event_loop_item item = {.type = type, .data = data};
utarray_push_back(loop->items, &item);
struct pollfd waiting = {.fd = fd, .events = events};
utarray_push_back(loop->waiting, &waiting);
return index;
}
/* Detach a file descriptor from the event loop.
* This invalidates all other indices into the event loop items, but leaves
* the ids of the event loop items valid. */
void event_loop_detach(event_loop *loop, int64_t index, int shall_close) {
struct pollfd *waiting_item =
(struct pollfd *) utarray_eltptr(loop->waiting, index);
struct pollfd *waiting_back = (struct pollfd *) utarray_back(loop->waiting);
if (shall_close) {
close(waiting_item->fd);
void event_loop_destroy(event_loop *loop) {
/* Clean up timer events. This is to make valgrind happy. */
aeTimeEvent *te = loop->timeEventHead;
while (te) {
aeTimeEvent *next = te->next;
free(te);
te = next;
}
*waiting_item = *waiting_back;
utarray_pop_back(loop->waiting);
event_loop_item *items_item =
(event_loop_item *) utarray_eltptr(loop->items, index);
event_loop_item *items_back = (event_loop_item *) utarray_back(loop->items);
*items_item = *items_back;
utarray_pop_back(loop->items);
aeDeleteEventLoop(loop);
}
/* Poll the file descriptors associated to this event loop.
* See http://linux.die.net/man/2/poll. The timeout is in milliseconds. */
int event_loop_poll(event_loop *loop, int timeout) {
return poll((struct pollfd *) utarray_front(loop->waiting),
utarray_len(loop->waiting), timeout);
void event_loop_add_file(event_loop *loop,
int fd,
int events,
event_loop_file_handler handler,
void *context) {
/* Try to add the file descriptor. */
int err = aeCreateFileEvent(loop, fd, events, handler, context);
/* If it cannot be added, increase the size of the event loop. */
if (err == AE_ERR && errno == ERANGE) {
err = aeResizeSetSize(loop, 3 * aeGetSetSize(loop) / 2);
CHECK(err == AE_OK);
err = aeCreateFileEvent(loop, fd, events, handler, context);
}
/* In any case, test if there were errors. */
CHECK(err == AE_OK);
}
/* Get the total number of file descriptors participating in the event loop. */
int64_t event_loop_size(event_loop *loop) {
return utarray_len(loop->waiting);
void event_loop_remove_file(event_loop *loop, int fd) {
aeDeleteFileEvent(loop, fd, EVENT_LOOP_READ | EVENT_LOOP_WRITE);
}
/* Get the pollfd structure associated to a file descriptor participating in the
* event loop. */
struct pollfd *event_loop_get(event_loop *loop, int64_t index) {
return (struct pollfd *) utarray_eltptr(loop->waiting, index);
int64_t event_loop_add_timer(event_loop *loop,
int64_t milliseconds,
event_loop_timer_handler handler,
void *context) {
return aeCreateTimeEvent(loop, milliseconds, handler, context, NULL);
}
/* Set the data connection information for participant in the event loop. */
void event_loop_set_data(event_loop *loop, int64_t index, void *data) {
event_loop_item *item =
(event_loop_item *) utarray_eltptr(loop->items, index);
item->data = data;
void event_loop_remove_timer(event_loop *loop, int64_t id) {
int err = aeDeleteTimeEvent(loop, id);
CHECK(err == AE_OK); /* timer id found? */
}
/* Get the data connection information for participant in the event loop. */
void *event_loop_get_data(event_loop *loop, int64_t index) {
event_loop_item *item =
(event_loop_item *) utarray_eltptr(loop->items, index);
return item->data;
void event_loop_run(event_loop *loop) {
aeMain(loop);
}
/* Return the type of connection. */
int event_loop_type(event_loop *loop, int64_t index) {
event_loop_item *item =
(event_loop_item *) utarray_eltptr(loop->items, index);
return item->type;
void event_loop_stop(event_loop *loop) {
aeStop(loop);
}