Future

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN


0.48    2022-01-26
        [CHANGES]
         * Implement the new AWAIT_ON_CANCEL API shape for Future::AsyncAwait

        [BUGFIXES]
         * Make sure to set rtime for immediate futures (RT134620)

0.47    2021-01-01
        [BUGFIXES]
         * Don't weaken() the waiting future in Future::Mutex as that causes
           it to be dropped in some situations

0.46    2020-10-19
        [CHANGES]
         * Provide AWAIT_CHAIN_CANCEL named method for compatibility with
           upcoming Future::AsyncAwait::Awaitable method rename

        [BUGFIXES]
         * Ensure that Future::Mutex returns proper cloned future instances
           when waiting (RT133563)

Changes  view on Meta::CPAN

0.26    2014/06/01 12:52:53
        [CHANGES]
         * Added ->is_failed accessor
         * Implement ->export_to_level in Future::Utils
         * Print a warning about lost sequence Futures
         * Allow Future->done and Future->fail as simple class constructors
           to return immediates
         * Added Future->unwrap

        [BUGFIXES]
         * Ensure that sequence futures are weaken()ed in the forward
           direction.
           **NOTE** This will potentially break existing code that depended on
             strong references. This old code was, however, broken.

0.25    2014/02/22 03:47:08
        [BUGFIXES]
         * Fix warning-matching test in unit test for both older and newer
           versions of Carp

0.24    2014/02/21 17:57:49

lib/Future/PP.pm  view on Meta::CPAN

package Future::PP 0.51;

use v5.14;
use warnings;
no warnings 'recursion'; # Disable the "deep recursion" warning

our @ISA = qw( Future::_base );

use Carp qw(); # don't import croak
use List::Util 1.29 qw( pairs pairkeys );
use Scalar::Util qw( weaken blessed reftype );
use Time::HiRes qw( gettimeofday );

our @CARP_NOT = qw( Future Future::_base Future::Utils );

use constant DEBUG => !!$ENV{PERL_FUTURE_DEBUG};

use constant STRICT => !!$ENV{PERL_FUTURE_STRICT};

# Callback flags
use constant {

lib/Future/PP.pm  view on Meta::CPAN


      $self->{reported} = 1 if $fail;

      if( $is_future ) {
         $done ? $code->done( @result ) :
         $fail ? $code->fail( @result ) :
                 $code->cancel;
      }
      elsif( $flags & (CB_SEQ_ONDONE|CB_SEQ_ONFAIL) ) {
         my ( undef, undef, $fseq ) = @$cb;
         if( !$fseq ) { # weaken()ed; it might be gone now
            # This warning should always be printed, even not in DEBUG mode.
            # It's always an indication of a bug
            Carp::carp +(DEBUG ? "${\$self->__selfstr} ($self->{constructed_at})"
                               : "${\$self->__selfstr} $self" ) .
               " lost a sequence Future";
            next;
         }

         my $f2;
         if( $done and $flags & CB_SEQ_ONDONE or

lib/Future/PP.pm  view on Meta::CPAN

         }
         else {
            $f2 = $self;
         }

         if( $f2->is_ready ) {
            $f2->on_ready( $fseq ) if !$f2->{cancelled};
         }
         else {
            push @{ $f2->{callbacks} }, [ CB_DONE|CB_FAIL, $fseq ];
            weaken( $f2->{callbacks}[-1][1] );
         }
      }
      else {
         $code->(
            ( $flags & CB_SELF   ? $self : () ),
            ( $flags & CB_RESULT ? @result : () ),
         );
      }
   }
}

lib/Future/PP.pm  view on Meta::CPAN


   my $is_future = blessed( $code ) && $code->isa( "Future" );
   $is_future or _callable( $code ) or
      Carp::croak "Expected \$code to be callable or a Future in ->on_cancel";

   $self->{ready} and return $self;

   push @{ $self->{on_cancel} }, $code;
   if( $is_future ) {
      push @{ $code->{revoke_when_ready} }, my $r = [ $self, \$self->{on_cancel}[-1] ];
      weaken( $r->[0] );
      weaken( $r->[1] );
   }

   return $self;
}

# An optimised version for Awaitable role
sub AWAIT_ON_CANCEL
{
   my $self = shift;
   my ( $code ) = @_;

lib/Future/PP.pm  view on Meta::CPAN

   push @{ $self->{on_cancel} }, $code;
}

sub AWAIT_CHAIN_CANCEL
{
   my $self = shift;
   my ( $f2 ) = @_;

   push @{ $self->{on_cancel} }, $f2;
   push @{ $f2->{revoke_when_ready} }, my $r = [ $self, \$self->{on_cancel}[-1] ];
   weaken( $r->[0] );
   weaken( $r->[1] );
}

sub _revoke_on_cancel
{
   my $self = shift;
   my ( $ref ) = @_;

   undef $$ref;
   $self->{empty_on_cancel_slots}++;

lib/Future/PP.pm  view on Meta::CPAN

   }

   my $fseq = $f1->new;
   $fseq->on_cancel( $f1 );

   # TODO: if anyone cares about the op name, we might have to synthesize it
   # from $flags
   $code = $f1->wrap_cb( sequence => $code ) unless $flags & (CB_SEQ_IMDONE|CB_SEQ_IMFAIL);

   push @{ $f1->{callbacks} }, [ CB_DONE|CB_FAIL|$flags, $code, $fseq ];
   weaken( $f1->{callbacks}[-1][2] );

   return $fseq;
}

sub then
{
   my $self = shift;
   my $done_code = shift;
   my $fail_code = ( @_ % 2 ) ? pop : undef;
   my @catch_list = @_;

lib/Future/PP.pm  view on Meta::CPAN

   my $pending = 0;
   $_->{ready} or $pending++ for @subs;

   # Look for immediate ready
   if( !$pending ) {
      $self->{result} = [ @subs ];
      $self->_mark_ready( "wait_all" );
      return $self;
   }

   weaken( my $weakself = $self );
   my $sub_on_ready = sub {
      return unless my $self = $weakself;

      $pending--;
      $pending and return;

      $self->{result} = [ pairkeys @{ $self->{subs} } ];
      $self->_mark_ready( "wait_all" );
   };

lib/Future/PP.pm  view on Meta::CPAN

      }
      else {
         $self->{result} = [ @{ $immediate_ready->{result} } ];
      }
      $self->_mark_ready( "wait_any" );
      return $self;
   }

   my $pending = 0;

   weaken( my $weakself = $self );
   my $sub_on_ready = sub {
      return unless my $self = $weakself;
      return if $self->{result} or $self->{failure}; # don't recurse on child ->cancel

      return if --$pending and $_[0]->{cancelled};

      if( $_[0]->{cancelled} ) {
         $self->{failure} = [ "All component futures were cancelled" ];
      }
      elsif( $_[0]->{failure} ) {

lib/Future/PP.pm  view on Meta::CPAN

   my $pending = 0;
   $_->{ready} or $pending++ for @subs;

   # Look for immediate done
   if( !$pending ) {
      $self->{result} = [ map { @{ $_->{result} } } @subs ];
      $self->_mark_ready( "needs_all" );
      return $self;
   }

   weaken( my $weakself = $self );
   my $sub_on_ready = sub {
      return unless my $self = $weakself;
      return if $self->{result} or $self->{failure}; # don't recurse on child ->cancel

      if( $_[0]->{cancelled} ) {
         $self->{failure} = [ "A component future was cancelled" ];
         $self->_cancel_subs;
         $self->_mark_ready( "needs_all" );
      }
      elsif( $_[0]->{failure} ) {

lib/Future/PP.pm  view on Meta::CPAN

   }

   if( $immediate_fail ) {
      $_->{reported} = 1 for @subs;
      # For consistency we'll pick the last one for the failure
      $self->{failure} = [ $subs[-1]->{failure} ];
      $self->_mark_ready( "needs_any" );
      return $self;
   }

   weaken( my $weakself = $self );
   my $sub_on_ready = sub {
      return unless my $self = $weakself;
      return if $self->{result} or $self->{failure}; # don't recurse on child ->cancel

      return if --$pending and $_[0]->{cancelled};

      if( $_[0]->{cancelled} ) {
         $self->{failure} = [ "All component futures were cancelled" ];
         $self->_mark_ready( "needs_any" );
      }



( run in 0.890 second using v1.01-cache-2.11-cpan-65fba6d93b7 )