Make the kqueue event driver compile on macOS (doesn't work yet).

This commit is contained in:
Sönke Ludwig 2017-01-22 18:43:29 +01:00
parent 2e09dcce41
commit c9c6d73f5e

View file

@ -7,9 +7,9 @@
module eventcore.drivers.kqueue; module eventcore.drivers.kqueue;
@safe: /*@nogc:*/ nothrow: @safe: /*@nogc:*/ nothrow:
/*version (FreeBSD) enum have_kqueue = true; version (FreeBSD) enum have_kqueue = true;
else version (OSX) enum have_kqueue = true; else version (OSX) enum have_kqueue = true;
else*/ enum have_kqueue = false; else enum have_kqueue = false;
static if (have_kqueue): static if (have_kqueue):
@ -17,7 +17,7 @@ public import eventcore.drivers.posix;
import eventcore.internal.utils; import eventcore.internal.utils;
import core.time : Duration; import core.time : Duration;
import core.sys.posix.sys.time : timespec; import core.sys.posix.sys.time : timespec, time_t;
version (OSX) import core.sys.darwin.sys.event; version (OSX) import core.sys.darwin.sys.event;
else version (FreeBSD) import core.sys.freebsd.sys.event; else version (FreeBSD) import core.sys.freebsd.sys.event;
@ -32,14 +32,14 @@ alias KqueueEventDriver = PosixEventDriver!KqueueEventLoop;
final class KqueueEventLoop : PosixEventLoop { final class KqueueEventLoop : PosixEventLoop {
private { private {
int m_queue; int m_queue;
kevent[] m_fds; kevent_t[] m_changes;
kevent[] m_events; kevent_t[] m_events;
} }
this() this()
{ @safe nothrow @nogc {
m_queue = kqueue(); m_queue = () @trusted { return kqueue(); } ();
enforce(m_queue >= 0, "Failed to create kqueue."); assert(m_queue >= 0, "Failed to create kqueue.");
} }
override bool doProcessEvents(Duration timeout) override bool doProcessEvents(Duration timeout)
@ -50,20 +50,26 @@ final class KqueueEventLoop : PosixEventLoop {
//print("wait %s", m_events.length); //print("wait %s", m_events.length);
timespec ts; timespec ts;
long secs, hnsecs; long secs, hnsecs;
dur.split!("seconds", "hnsecs")(secs, hnsecs); timeout.split!("seconds", "hnsecs")(secs, hnsecs);
ts.tv_sec = cast(time_t)secs; ts.tv_sec = cast(time_t)secs;
ts.tv_nsec = hnsecs * 100; ts.tv_nsec = hnsecs * 100;
auto ret = kevent(m_queue, m_fds, m_fds.length, m_events, m_events.length, timeout == Duration.max ? null : &ts); auto ret = kevent(m_queue, m_changes.ptr, cast(int)m_changes.length, m_events.ptr, cast(int)m_events.length, timeout == Duration.max ? null : &ts);
m_changes.length = 0;
m_changes.assumeSafeAppend();
if (ret > 0) { if (ret > 0) {
foreach (ref evt; m_events[0 .. ret]) { foreach (ref evt; m_events[0 .. ret]) {
//print("event %s %s", evt.data.fd, evt.events); //print("event %s %s", evt.data.fd, evt.events);
auto fd = cast(FD)evt.ident; assert(evt.ident <= uint.max);
if (evt.flags & EV_READ) notify!(EventType.read)(fd); auto fd = cast(FD)cast(int)evt.ident;
if (evt.flags & EV_WRITE) notify!(EventType.write)(fd); if (evt.flags & (EV_EOF|EV_ERROR))
if (evt.flags & EV_ERROR) notify!(EventType.status)(fd); notify!(EventType.status)(fd);
else if (evt.flags & EV_EOF) notify!(EventType.status)(fd); switch (evt.filter) {
default: break;
case EVFILT_READ: notify!(EventType.read)(fd); break;
case EVFILT_WRITE: notify!(EventType.write)(fd); break;
}
// EV_SIGNAL, EV_TIMEOUT // EV_SIGNAL, EV_TIMEOUT
} }
return true; return true;
@ -80,30 +86,32 @@ final class KqueueEventLoop : PosixEventLoop {
override void registerFD(FD fd, EventMask mask) override void registerFD(FD fd, EventMask mask)
{ {
//print("register %s %s", fd, mask); //print("register %s %s", fd, mask);
auto idx = allocSlot(fd); kevent_t ev;
kevent* ev = &m_events[idx];
ev.ident = fd; ev.ident = fd;
ev.flags = EV_ADD|EV_ET|EV_ENABLE; ev.flags = EV_ADD|EV_CLEAR|EV_ENABLE;
if (mask & EventMask.read) ev.filter |= EVFILT_READ; if (mask & EventMask.read) ev.filter |= EVFILT_READ;
if (mask & EventMask.write) ev.filter |= EVFILT_WRITE; if (mask & EventMask.write) ev.filter |= EVFILT_WRITE;
if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP; //if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP;
m_changes ~= ev;
} }
override void unregisterFD(FD fd) override void unregisterFD(FD fd)
{ {
auto idx = m_eventMap[fd]; kevent_t ev;
m_events[idx].flags = EV_REMOVE; ev.ident = fd;
ev.flags = EV_DELETE;
m_changes ~= ev;
} }
override void updateFD(FD fd, EventMask mask) override void updateFD(FD fd, EventMask mask)
{ {
//print("update %s %s", fd, mask); //print("update %s %s", fd, mask);
auto idx = m_eventMap[fd]; kevent_t ev;
epoll_event* ev = &m_events[idx];
ev.filter = 0; ev.filter = 0;
ev.events |= EPOLLET; ev.flags |= EV_CLEAR;
if (mask & EventMask.read) ev.filter |= EVFILT_READ; if (mask & EventMask.read) ev.filter |= EVFILT_READ;
if (mask & EventMask.write) ev.filter |= EVFILT_WRITE; if (mask & EventMask.write) ev.filter |= EVFILT_WRITE;
if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP; //if (mask & EventMask.status) ev.events |= EPOLLERR|EPOLLRDHUP;
m_changes ~= ev;
} }
} }