in Sources/NIOPosix/SelectorKqueue.swift [204:262]
func whenReady0(strategy: SelectorStrategy, onLoopBegin loopStart: () -> Void, _ body: (SelectorEvent<R>) throws -> Void) throws -> Void {
assert(self.myThread == NIOThread.current)
guard self.lifecycleState == .open else {
throw IOError(errnoCode: EBADF, reason: "can't call whenReady for selector as it's \(self.lifecycleState).")
}
let timespec = Selector.toKQueueTimeSpec(strategy: strategy)
let ready = try timespec.withUnsafeOptionalPointer { ts in
Int(try KQueue.kevent(kq: self.selectorFD, changelist: nil, nchanges: 0, eventlist: events, nevents: Int32(eventsCapacity), timeout: ts))
}
loopStart()
for i in 0..<ready {
let ev = events[i]
let filter = Int32(ev.filter)
let eventRegistrationID = SelectorRegistrationID(kqueueUData: ev.udata)
guard Int32(ev.flags) & EV_ERROR == 0 else {
throw IOError(errnoCode: Int32(ev.data), reason: "kevent returned with EV_ERROR set: \(String(describing: ev))")
}
guard filter != EVFILT_USER, let registration = registrations[Int(ev.ident)] else {
continue
}
guard eventRegistrationID == registration.registrationID else {
continue
}
var selectorEvent: SelectorEventSet = ._none
switch filter {
case EVFILT_READ:
selectorEvent.formUnion(.read)
fallthrough // falling through here as `EVFILT_READ` also delivers `EV_EOF` (meaning `.readEOF`)
case EVFILT_EXCEPT:
if Int32(ev.flags) & EV_EOF != 0 && registration.interested.contains(.readEOF) {
// we only add `.readEOF` if it happened and the user asked for it
selectorEvent.formUnion(.readEOF)
}
case EVFILT_WRITE:
selectorEvent.formUnion(.write)
default:
// We only use EVFILT_USER, EVFILT_READ, EVFILT_EXCEPT and EVFILT_WRITE.
fatalError("unexpected filter \(ev.filter)")
}
if ev.fflags != 0 {
selectorEvent.formUnion(.reset)
}
// we can only verify the events for i == 0 as for i > 0 the user might have changed the registrations since then.
assert(i != 0 || selectorEvent.isSubset(of: registration.interested), "selectorEvent: \(selectorEvent), registration: \(registration)")
// in any case we only want what the user is currently registered for & what we got
selectorEvent = selectorEvent.intersection(registration.interested)
guard selectorEvent != ._none else {
continue
}
try body((SelectorEvent(io: selectorEvent, registration: registration)))
}
growEventArrayIfNeeded(ready: ready)
}