+ 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 timeval *tv) {
+ timeout->cb = cb;
+ timeout->data = data;
+ timeout->node.data = timeout;
+
+ timeout_set(loop, timeout, tv);
+}
+
+void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv) {
+ if(timerisset(&timeout->tv)) {
+ splay_unlink_node(&loop->timeouts, &timeout->node);
+ }
+
+ if(!loop->now.tv_sec) {
+ gettimeofday(&loop->now, NULL);
+ }
+
+ timeradd(&loop->now, tv, &timeout->tv);
+
+ if(!splay_insert_node(&loop->timeouts, &timeout->node)) {
+ abort();
+ }
+}
+
+void timeout_del(event_loop_t *loop, timeout_t *timeout) {
+ if(!timeout->cb) {
+ return;
+ }
+
+ loop->deletion = true;
+
+ splay_unlink_node(&loop->timeouts, &timeout->node);
+ timeout->cb = 0;
+ timeout->tv = (struct timeval) {
+ 0, 0
+ };
+}
+
+static int signal_compare(const signal_t *a, const signal_t *b) {
+ return (int)a->signum - (int)b->signum;
+}
+
+static void signalio_handler(event_loop_t *loop, void *data, int flags) {
+ (void)data;
+ (void)flags;
+ unsigned char signum;
+
+ if(read(loop->pipefd[0], &signum, 1) != 1) {
+ return;
+ }
+
+ signal_t *sig = splay_search(&loop->signals, &((signal_t) {
+ .signum = signum
+ }));
+
+ if(sig) {
+ sig->cb(loop, sig->data);
+ }