Acme-Sort-Sleep

 view release on metacpan or  search on metacpan

local/lib/perl5/IO/Async/Internals/TimeQueue.pm  view on Meta::CPAN


package # hide from CPAN
  IO::Async::Internals::TimeQueue;

use strict;
use warnings;

use Carp;

use Time::HiRes qw( time );

BEGIN {
   my @methods = qw( next_time _enqueue cancel _fire );
   if( eval { require Heap::Fibonacci } ) {
      unshift our @ISA, "Heap::Fibonacci";
      require Heap::Elem;
      no strict 'refs';
      *$_ = \&{"HEAP_$_"} for @methods;
   }
   else {
      no strict 'refs';
      *$_ = \&{"ARRAY_$_"} for "new", @methods;
   }
}

# High-level methods

sub enqueue
{
   my $self = shift;
   my ( %params ) = @_;

   my $code = delete $params{code};
   ref $code or croak "Expected 'code' to be a reference";

   defined $params{time} or croak "Expected 'time'";
   my $time = $params{time};

   $self->_enqueue( $time, $code );
}

sub fire
{
   my $self = shift;
   my ( %params ) = @_;

   my $now = exists $params{now} ? $params{now} : time;
   $self->_fire( $now );
}

# Implementation using a Perl array

use constant {
   TIME => 0,
   CODE => 1,
};

sub ARRAY_new
{
   my $class = shift;
   return bless [], $class;
}

sub ARRAY_next_time
{
   my $self = shift;
   return @$self ? $self->[0]->[TIME] : undef;
}

sub ARRAY__enqueue
{
   my $self = shift;
   my ( $time, $code ) = @_;

   # TODO: This could be more efficient maybe using a binary search
   my $idx = 0;
   $idx++ while $idx < @$self and $self->[$idx][TIME] <= $time;
   splice @$self, $idx, 0, ( my $elem = [ $time, $code ]);

   return $elem;
}

sub ARRAY_cancel
{
   my $self = shift;
   my ( $id ) = @_;

   @$self = grep { $_ != $id } @$self;
}

sub ARRAY__fire
{
   my $self = shift;
   my ( $now ) = @_;

   my $count = 0;

   while( @$self ) {
      last if( $self->[0]->[TIME] > $now );

      my $top = shift @$self;

      $top->[CODE]->();
      $count++;
   }

   return $count;
}

# Implementation using Heap::Fibonacci

sub HEAP_next_time
{
   my $self = shift;

   my $top = $self->top;

   return defined $top ? $top->time : undef;
}

sub HEAP__enqueue



( run in 1.558 second using v1.01-cache-2.11-cpan-39bf76dae61 )