+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#endif
+#define ULOOP_MAX_EVENTS 10
+
+struct uloop_timeout *first_timeout;
+static int poll_fd;
+static bool cancel;
+
+#ifdef USE_KQUEUE
+
+int uloop_init(void)
+{
+ poll_fd = kqueue();
+ if (poll_fd < 0)
+ return -1;
+
+ return 0;
+}
+
+
+static uint16_t get_flags(unsigned int flags, unsigned int mask)
+{
+ uint16_t kflags = 0;
+
+ if (!(flags & mask))
+ return EV_DELETE;
+
+ kflags = EV_ADD;
+ if (flags & ULOOP_EDGE_TRIGGER)
+ kflags |= EV_CLEAR;
+
+ return kflags;
+}
+
+static int register_poll(struct uloop_fd *fd, unsigned int flags)
+{
+ struct timespec timeout = { 0, 0 };
+ struct kevent ev[2];
+ unsigned int changed;
+ int nev = 0;
+
+ changed = fd->kqflags ^ flags;
+ if (changed & ULOOP_EDGE_TRIGGER)
+ changed |= flags;
+
+ if (changed & ULOOP_READ) {
+ uint16_t kflags = get_flags(flags, ULOOP_READ);
+ EV_SET(&ev[nev++], fd->fd, EVFILT_READ, kflags, 0, 0, fd);
+ }
+
+ if (changed & ULOOP_WRITE) {
+ uint16_t kflags = get_flags(flags, ULOOP_WRITE);
+ EV_SET(&ev[nev++], fd->fd, EVFILT_READ, kflags, 0, 0, fd);
+ }
+
+ if (nev && (kevent(poll_fd, ev, nev, NULL, 0, &timeout) == -1))
+ return -1;
+
+ fd->kqflags = flags;
+ return 0;
+}
+
+int uloop_fd_delete(struct uloop_fd *sock)
+{
+ sock->registered = false;
+ return register_poll(sock, 0);
+}
+
+static void uloop_run_events(int timeout)
+{
+ struct kevent events[ULOOP_MAX_EVENTS];
+ struct timespec ts;
+ int nfds, n;
+
+ if (timeout < 0) {
+ ts.tv_sec = 0;
+ ts.tv_nsec = 0;
+ } else {
+ ts.tv_sec = timeout / 1000;
+ ts.tv_nsec = timeout * 1000000;
+ }
+
+ nfds = kevent(poll_fd, NULL, 0, events, ARRAY_SIZE(events), &ts);
+ for(n = 0; n < nfds; ++n)
+ {
+ struct uloop_fd *u = events[n].udata;
+ unsigned int ev = 0;
+
+ if(events[n].flags & EV_ERROR) {
+ u->error = true;
+ uloop_fd_delete(u);
+ }
+
+ if(events[n].filter == EVFILT_READ)
+ ev |= ULOOP_READ;
+ else if (events[n].filter == EVFILT_WRITE)
+ ev |= ULOOP_WRITE;
+
+ if(events[n].flags & EV_EOF)
+ u->eof = true;
+ else if (!ev)
+ continue;
+
+ if(u->cb)
+ u->cb(u, ev);
+ }
+}
+
+#endif
+
+#ifdef USE_EPOLL