run method

Future<void> run()

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,
            );
          }
        }
      }
    }
  }
}