- return unless PostEventLoop();
- }
- exit 0;
-}
-
-### The fallback IO::Poll-based event loop. Gets installed as EventLoop if
-### IO::Epoll fails to load.
-sub PollEventLoop {
- my $class = shift;
-
- my PublicInbox::DS $pob;
-
- while (1) {
- my $timeout = RunTimers();
-
- # the following sets up @poll as a series of ($poll,$event_mask)
- # items, then uses IO::Poll::_poll, implemented in XS, which
- # modifies the array in place with the even elements being
- # replaced with the event masks that occured.
- my @poll;
- while ( my ($fd, $sock) = each %DescriptorMap ) {
- push @poll, $fd, $sock->{event_watch};
- }
-
- # if nothing to poll, either end immediately (if no timeout)
- # or just keep calling the callback
- unless (@poll) {
- select undef, undef, undef, ($timeout / 1000);
- return unless PostEventLoop();
- next;
- }
-
- my $count = IO::Poll::_poll($timeout, @poll);
- unless ($count >= 0) {
- return unless PostEventLoop();
- next;
- }
-
- # Fetch handles with read events
- while (@poll) {
- my ($fd, $state) = splice(@poll, 0, 2);
- next unless $state;
-
- $pob = $DescriptorMap{$fd};
-
- $pob->event_read if $state & POLLIN && ! $pob->{closed};
- $pob->event_write if $state & POLLOUT && ! $pob->{closed};
- event_end($pob) if $state & (POLLERR|POLLHUP) && ! $pob->{closed};
- }
-
- return unless PostEventLoop();
- }
-
- exit 0;
-}
-
-### The kqueue-based event loop. Gets installed as EventLoop if IO::KQueue works
-### okay.
-sub KQueueEventLoop {
- my $class = shift;
-
- while (1) {
- my $timeout = RunTimers();
- my @ret = eval { $KQueue->kevent($timeout) };
- if (my $err = $@) {
- # workaround https://rt.cpan.org/Ticket/Display.html?id=116615
- if ($err =~ /Interrupted system call/) {
- @ret = ();
- } else {
- die $err;
- }
- }
-
- foreach my $kev (@ret) {
- my ($fd, $filter, $flags, $fflags) = @$kev;
- my PublicInbox::DS $pob = $DescriptorMap{$fd};
-
- DebugLevel >= 1 && $class->DebugMsg("Event: fd=%d (%s), flags=%d \@ %s\n",
- $fd, ref($pob), $flags, time);
-
- $pob->event_read if $filter == IO::KQueue::EVFILT_READ() && !$pob->{closed};
- $pob->event_write if $filter == IO::KQueue::EVFILT_WRITE() && !$pob->{closed};
- if ($flags == IO::KQueue::EV_EOF() && !$pob->{closed}) {
- event_end($pob);
- }
- }
- return unless PostEventLoop();
- }
-
- exit(0);