Acme-Sort-Sleep
view release on metacpan or search on metacpan
local/lib/perl5/Future.pm view on Meta::CPAN
return $self;
}
=head2 needs_all
$future = Future->needs_all( @subfutures )
Returns a new C<Future> instance that will indicate it is ready once all of the
sub future objects given to it indicate that they have completed successfully,
or when any of them indicates that they have failed. If any sub future fails,
then this will fail immediately, and the remaining subs not yet ready will be
cancelled. Any component futures that are cancelled will cause an immediate
failure of the result.
If successful, its result will be a concatenated list of the results of all
its component futures, in corresponding order. If it fails, its failure will
be that of the first component future that failed. To access each component
future's results individually, use C<done_futures>.
When given an empty list this constructor returns a new immediately-done
future.
This constructor would primarily be used by users of asynchronous interfaces.
=cut
sub needs_all
{
my $class = shift;
my @subs = @_;
unless( @subs ) {
my $self = $class->done;
$self->{subs} = [];
return $self;
}
my $self = Future->_new_convergent( \@subs );
# Look for immediate fail
my $immediate_fail;
foreach my $sub ( @subs ) {
$sub->{ready} and $sub->{failure} and $immediate_fail = $sub, last;
}
if( $immediate_fail ) {
foreach my $sub ( @subs ) {
$sub->{ready} or $sub->cancel;
}
$self->{failure} = [ $immediate_fail->failure ];
$self->_mark_ready( "needs_all" );
return $self;
}
my $pending = 0;
$_->{ready} or $pending++ for @subs;
# Look for immediate done
if( !$pending ) {
$self->{result} = [ map { $_->get } @subs ];
$self->_mark_ready( "needs_all" );
return $self;
}
weaken( my $weakself = $self );
my $sub_on_ready = sub {
return unless $weakself;
return if $weakself->{result} or $weakself->{failure}; # don't recurse on child ->cancel
if( $_[0]->{cancelled} ) {
$weakself->{failure} = [ "A component future was cancelled" ];
foreach my $sub ( @subs ) {
$sub->cancel if !$sub->{ready};
}
$weakself->_mark_ready( "needs_all" );
}
elsif( my @failure = $_[0]->failure ) {
$weakself->{failure} = \@failure;
foreach my $sub ( @subs ) {
$sub->cancel if !$sub->{ready};
}
$weakself->_mark_ready( "needs_all" );
}
else {
$pending--;
$pending and return;
$weakself->{result} = [ map { $_->get } @subs ];
$weakself->_mark_ready( "needs_all" );
}
};
foreach my $sub ( @subs ) {
$sub->{ready} or $sub->on_ready( $sub_on_ready );
}
return $self;
}
=head2 needs_any
$future = Future->needs_any( @subfutures )
Returns a new C<Future> instance that will indicate it is ready once any of
the sub future objects given to it indicate that they have completed
successfully, or when all of them indicate that they have failed. If any sub
future succeeds, then this will succeed immediately, and the remaining subs
not yet ready will be cancelled. Any component futures that are cancelled are
ignored, apart from the final component left; at which point the result will
be a failure.
If successful, its result will be that of the first component future that
succeeded. If it fails, its failure will be that of the last component future
to fail. To access the other failures, use C<failed_futures>.
Normally when this future completes successfully, only one of its component
futures will be done. If it is constructed with multiple that are already done
however, then all of these will be returned from C<done_futures>. Users should
be careful to still check all the results from C<done_futures> in that case.
When given an empty list this constructor returns an immediately-failed
future.
This constructor would primarily be used by users of asynchronous interfaces.
=cut
sub needs_any
{
my $class = shift;
my @subs = @_;
unless( @subs ) {
my $self = $class->fail( "Cannot ->needs_any with no subfutures" );
$self->{subs} = [];
return $self;
}
my $self = Future->_new_convergent( \@subs );
# Look for immediate done
my $immediate_done;
my $pending = 0;
foreach my $sub ( @subs ) {
$sub->{ready} and !$sub->{failure} and $immediate_done = $sub, last;
$sub->{ready} or $pending++;
}
( run in 0.659 second using v1.01-cache-2.11-cpan-140bd7fdf52 )