From 831ac641e8c23e3c87931b902527d7f5600fd80a Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Mon, 11 Sep 2023 09:41:30 +0000 Subject: dspoll: switch to the documented IO::Poll API IO::Poll::_poll has always been an undocumented API. While it's remained working so far (since the early 2000s with Danga::Socket), I'm uncomfortable continuing with it moving forward since it's not documented (the leading underscore typically means it's not meant to be used by 3rd-parties). So switch to the documented API and just learn to live with some redundant object references and awkwardness in the API. --- lib/PublicInbox/DSPoll.pm | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) (limited to 'lib/PublicInbox/DSPoll.pm') diff --git a/lib/PublicInbox/DSPoll.pm b/lib/PublicInbox/DSPoll.pm index fc282de0..8ab5d19f 100644 --- a/lib/PublicInbox/DSPoll.pm +++ b/lib/PublicInbox/DSPoll.pm @@ -13,34 +13,33 @@ use v5.12; use IO::Poll; use PublicInbox::Syscall qw(EPOLLONESHOT EPOLLIN EPOLLOUT); -sub new { bless {}, __PACKAGE__ } # fd => events +sub new { bless { poll => IO::Poll->new }, __PACKAGE__ } # fd => events sub ep_wait { my ($self, $maxevents, $timeout_msec, $events) = @_; - my @pset; - while (my ($fd, $events) = each %$self) { - my $pevents = $events & EPOLLIN ? POLLIN : 0; - $pevents |= $events & EPOLLOUT ? POLLOUT : 0; - push(@pset, $fd, $pevents); - } - @$events = (); - my $n = IO::Poll::_poll($timeout_msec, @pset); - if ($n >= 0) { - for (my $i = 0; $i < @pset; ) { - my $fd = $pset[$i++]; - my $revents = $pset[$i++] or next; - delete($self->{$fd}) if $self->{$fd} & EPOLLONESHOT; - push @$events, $fd; - } - my $nevents = scalar @$events; - if ($n != $nevents) { - warn "BUG? poll() returned $n, but got $nevents"; - } + $self->{poll}->poll($timeout_msec/1000) > 0 or return (@$events = ()); + my @io = $self->{poll}->handles(POLLIN|POLLOUT); + @$events = map { fileno($_) } @io; + for (@$events) { + my $io = shift @io; + $self->{poll}->remove($io) if delete($self->{oneshot}->{$_}); } } -sub ep_del { delete($_[0]->{fileno($_[1])}); 0 } -sub ep_add { $_[0]->{fileno($_[1])} = $_[2]; 0 } +sub ep_del { + my ($self, $io) = @_; + delete $self->{oneshot}->{fileno($io)}; + $self->{poll}->remove($io); + 0; +} + +sub ep_add { + my ($self, $io, $ev) = @_; + $self->{oneshot}->{fileno($io)} = 1 if $ev & EPOLLONESHOT; + $self->{poll}->mask($io, ($ev & EPOLLIN ? POLLIN : 0) | + ($ev & EPOLLOUT ? POLLOUT : 0)); + 0; +} no warnings 'once'; *ep_mod = \&ep_add; -- cgit v1.2.3-24-ge0c7