+void signal_del(event_loop_t *loop, signal_t *sig) {
+ assert(sig->cb);
+
+ loop->deletion = true;
+
+ splay_unlink_node(&loop->signals, &sig->node);
+ sig->cb = NULL;
+
+ if(!loop->signals.count && loop->pipefd[0] != -1) {
+ pipe_exit(loop);
+ }
+}
+
+void idle_set(event_loop_t *loop, idle_cb_t cb, void *data) {
+ loop->idle_cb = cb;
+ loop->idle_data = data;
+}
+
+bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) {
+ assert(mutex);
+
+ fd_set readable;
+ fd_set writable;
+
+ while(loop->running) {
+ clock_gettime(EVENT_CLOCK, &loop->now);
+ struct timespec it, ts = {3600, 0};
+
+ while(loop->timeouts.head) {
+ timeout_t *timeout = loop->timeouts.head->data;
+
+ if(timespec_lt(&timeout->tv, &loop->now)) {
+ timeout_disable(loop, timeout);
+ timeout->cb(loop, timeout->data);
+ } else {
+ timespec_sub(&timeout->tv, &loop->now, &ts);
+ break;
+ }
+ }
+
+ if(loop->idle_cb) {
+ it = loop->idle_cb(loop, loop->idle_data);
+
+ if(it.tv_sec >= 0 && timespec_lt(&it, &ts)) {
+ ts = it;
+ }
+ }
+
+ memcpy(&readable, &loop->readfds, sizeof(readable));
+ memcpy(&writable, &loop->writefds, sizeof(writable));
+
+ int fds = 0;