+ } else if(a->tv.tv_sec > b->tv.tv_sec) {
+ return 1;
+ } else if(a->tv.tv_nsec < b->tv.tv_nsec) {
+ return -1;
+ } else if(a->tv.tv_nsec > b->tv.tv_nsec) {
+ return 1;
+ } else if(a < b) {
+ return -1;
+ } else if(a > b) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void io_add(event_loop_t *loop, io_t *io, io_cb_t cb, void *data, int fd, int flags) {
+ assert(!io->cb);
+
+ io->fd = fd;
+ io->cb = cb;
+ io->data = data;
+ io->node.data = io;
+
+ io_set(loop, io, flags);
+
+ splay_node_t *node = splay_insert_node(&loop->ios, &io->node);
+ assert(node);
+ (void)node;
+}
+
+void io_set(event_loop_t *loop, io_t *io, int flags) {
+ assert(io->cb);
+
+ io->flags = flags;
+
+ if(flags & IO_READ) {
+ FD_SET(io->fd, &loop->readfds);
+ } else {
+ FD_CLR(io->fd, &loop->readfds);
+ }
+
+ if(flags & IO_WRITE) {
+ FD_SET(io->fd, &loop->writefds);
+ } else {
+ FD_CLR(io->fd, &loop->writefds);
+ }
+}
+
+void io_del(event_loop_t *loop, io_t *io) {
+ assert(io->cb);
+
+ loop->deletion = true;
+
+ io_set(loop, io, 0);
+
+ splay_unlink_node(&loop->ios, &io->node);
+ io->cb = NULL;
+}
+
+void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timespec *tv) {
+ timeout->cb = cb;
+ timeout->data = data;
+
+ timeout_set(loop, timeout, tv);
+}
+
+void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timespec *tv) {
+ assert(timeout->cb);
+
+ if(timeout->node.data) {
+ splay_unlink_node(&loop->timeouts, &timeout->node);
+ } else {
+ timeout->node.data = timeout;
+ }
+
+ if(!loop->now.tv_sec) {
+ clock_gettime(EVENT_CLOCK, &loop->now);
+ }
+
+ timespec_add(&loop->now, tv, &timeout->tv);
+
+ if(!splay_insert_node(&loop->timeouts, &timeout->node)) {
+ abort();
+ }
+
+ loop->deletion = true;
+}
+
+static void timeout_disable(event_loop_t *loop, timeout_t *timeout) {
+ if(timeout->node.data) {
+ splay_unlink_node(&loop->timeouts, &timeout->node);
+ timeout->node.data = NULL;
+ }
+
+ timespec_clear(&timeout->tv);
+}
+
+void timeout_del(event_loop_t *loop, timeout_t *timeout) {
+ if(!timeout->cb) {
+ return;
+ }
+
+ if(timeout->node.data) {
+ timeout_disable(loop, timeout);
+ }
+
+ timeout->cb = NULL;
+ loop->deletion = true;
+}