+void timeout_add(event_loop_t *loop, timeout_t *timeout, timeout_cb_t cb, void *data, struct timeval *tv) {
+ if(!timeout->cb)
+ timeout->tv = (struct timeval) {
+ 0, 0
+ };
+
+ 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) {
+ 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);
+}