-=head2 C<< CLASS->AddTimer( $seconds, $coderef ) >>
-
-Add a timer to occur $seconds from now. $seconds may be fractional, but timers
-are not guaranteed to fire at the exact time you ask for.
-
-Returns a timer object which you can call C<< $timer->cancel >> on if you need to.
-
-=cut
-sub AddTimer {
- my $class = shift;
- my ($secs, $coderef) = @_;
-
- my $fire_time = Time::HiRes::time() + $secs;
-
- my $timer = bless [$fire_time, $coderef], "PublicInbox::DS::Timer";
-
- if (!@Timers || $fire_time >= $Timers[-1][0]) {
- push @Timers, $timer;
- return $timer;
- }
-
- # Now, where do we insert? (NOTE: this appears slow, algorithm-wise,
- # but it was compared against calendar queues, heaps, naive push/sort,
- # and a bunch of other versions, and found to be fastest with a large
- # variety of datasets.)
- for (my $i = 0; $i < @Timers; $i++) {
- if ($Timers[$i][0] > $fire_time) {
- splice(@Timers, $i, 0, $timer);
- return $timer;
- }
- }
-
- die "Shouldn't get here.";
-}
-
-sub _InitPoller
-{
- return if $DoneInit;
- $DoneInit = 1;
-
- if ($HAVE_KQUEUE) {
- $KQueue = IO::KQueue->new();
- $HaveKQueue = $KQueue >= 0;
- if ($HaveKQueue) {
- *EventLoop = *KQueueEventLoop;
- }
- }
- elsif (PublicInbox::Syscall::epoll_defined()) {
- $Epoll = eval { epoll_create(1024); };
- $HaveEpoll = defined $Epoll && $Epoll >= 0;
- if ($HaveEpoll) {
- *EventLoop = *EpollEventLoop;
- }
- }
-
- if (!$HaveEpoll && !$HaveKQueue) {
- require IO::Poll;
- *EventLoop = *PollEventLoop;
- }
+# caller sets return value to $Epoll
+sub _InitPoller () {
+ if (PublicInbox::Syscall::epoll_defined()) {
+ my $fd = epoll_create();
+ die "epoll_create: $!" if $fd < 0;
+ open($ep_io, '+<&=', $fd) or return;
+ my $fl = fcntl($ep_io, F_GETFD, 0);
+ fcntl($ep_io, F_SETFD, $fl | FD_CLOEXEC);
+ $fd;
+ } else {
+ my $cls;
+ for (qw(DSKQXS DSPoll)) {
+ $cls = "PublicInbox::$_";
+ last if eval "require $cls";
+ }
+ $cls->import(qw(epoll_ctl epoll_wait));
+ $cls->new;
+ }