about summary refs log tree commit homepage
path: root/lib/PublicInbox/DSPoll.pm
diff options
context:
space:
mode:
authorEric Wong <e@80x24.org>2023-09-11 09:41:30 +0000
committerEric Wong <e@80x24.org>2023-09-11 18:51:16 +0000
commit831ac641e8c23e3c87931b902527d7f5600fd80a (patch)
treeac2dacf36c064faa67c0d4cc6db1bcac9e1705f5 /lib/PublicInbox/DSPoll.pm
parent57bc493d8e137f50343c8ef9256255b8963dab30 (diff)
downloadpublic-inbox-831ac641e8c23e3c87931b902527d7f5600fd80a.tar.gz
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.
Diffstat (limited to 'lib/PublicInbox/DSPoll.pm')
-rw-r--r--lib/PublicInbox/DSPoll.pm43
1 files changed, 21 insertions, 22 deletions
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;