run method
Implementation
Future<void> run() async {
assert(_epollFd > 0);
assert(_eventFd > 0);
_sendPort.send(_InitializedEvent(sendPort: _receivePort.sendPort));
/// Add the event fd to the epoll instance.
/// so we get notified of new commands even when we're in
/// epoll_wait right now.
_add(
fd: _eventFd,
flags: {EpollFlag.inReady},
listenerId: _eventFdCap,
callback: _noop,
callbackContext: null,
);
while (_shouldRun) {
// let the microtask loop run so events the receivePort listener
// is invoked and commands are added to the cmd queue
await _waitForEvents();
processCommands();
// It could be we received a stop command.
// In that case, finish early here.
if (!_shouldRun) {
break;
}
final ok = _retry(() => libc.epoll_wait(
_epollFd,
_events,
_maxEvents,
-1, // wait indefinitely
));
if (ok < 0) {
throw LinuxError('Could not wait for epoll events.', 'epoll_wait', libc.errno);
}
if (ok > 0) {
// process any epoll events
for (var i = 0; i < ok; i++) {
final event = _events + i;
final capability = _capabilityMap[event.ref.data.u64]!;
final flags = <EpollFlag>{};
for (final flag in EpollFlag.values) {
if (event.ref.events & flag._value != 0) {
flags.add(flag);
}
}
if (capability == _eventFdCap) {
// do nothing
} else {
assert(capability is Capability);
// Find and invoke the handler.
final handler = _handlerMap[capability]!;
try {
final value = handler.callback(this, handler.fd, flags, handler.callbackContext);
_sendEvent(
handlerId: handler.id,
event: value,
);
} on Exception catch (err, st) {
_sendError(
handlerId: handler.id,
error: err,
stackTrace: st,
);
}
}
}
}
}
}