Acme-Sort-Sleep
view release on metacpan or search on metacpan
local/lib/perl5/Future/Phrasebook.pod view on Meta::CPAN
of the component futures to complete. This can be used to form a sequence with
concurrency.
{ FIRST_A(); FIRST_B() }
SECOND();
Z<>
my $f = Future->wait_all( FIRST_A(), FIRST_B() )
->then( sub { SECOND() } );
Unlike in the call/return case, this can perform the work of C<FIRST_A()> and
C<FIRST_B()> concurrently, only proceeding to C<SECOND()> when both are ready.
The result of the C<wait_all> C<Future> is the list of its component
C<Future>s. This can be used to obtain the results.
SECOND( FIRST_A(), FIRST_B() );
Z<>
my $f = Future->wait_all( FIRST_A(), FIRST_B() )
->then( sub {
my ( $f_a, $f_b ) = @_
SECOND( $f_a->get, $f_b->get );
} );
Because the C<get> method will re-raise an exception caused by a failure of
either of the C<FIRST> functions, the second stage will fail if any of the
initial Futures failed.
As this is likely to be the desired behaviour most of the time, this kind of
control flow can be written slightly neater using C<< Future->needs_all >>
instead.
my $f = Future->needs_all( FIRST_A(), FIRST_B() )
->then( sub { SECOND( @_ ) } );
The C<get> method of a C<needs_all> convergent Future returns a concatenated
list of the results of all its component Futures, as the only way it will
succeed is if all the components do.
=head2 Waiting on Multiple Calls of One Function
Because the C<wait_all> and C<needs_all> constructors take an entire list of
C<Future> instances, they can be conveniently used with C<map> to wait on the
result of calling a function concurrently once per item in a list.
my @RESULT = map { FUNC( $_ ) } @ITEMS;
PROCESS( @RESULT );
Again, the C<needs_all> version allows more convenient access to the list of
results.
my $f = Future->needs_all( map { F_FUNC( $_ ) } @ITEMS )
->then( sub {
my @RESULT = @_;
F_PROCESS( @RESULT )
} );
This form of the code starts every item's future concurrently, then waits for
all of them. If the list of C<@ITEMS> is potentially large, this may cause a
problem due to too many items running at once. Instead, the
C<Future::Utils::fmap> family of functions can be used to bound the
concurrency, keeping at most some given number of items running, starting new
ones as existing ones complete.
my $f = fmap {
my $item = shift;
F_FUNC( $item )
} foreach => \@ITEMS;
By itself, this will not actually act concurrently as it will only keep one
Future outstanding at a time. The C<concurrent> flag lets it keep a larger
number "in flight" at any one time:
my $f = fmap {
my $item = shift;
F_FUNC( $item )
} foreach => \@ITEMS, concurrent => 10;
The C<fmap> and C<fmap_scalar> functions return a Future that will eventually
give the collected results of the individual item futures, thus making them
similar to perl's C<map> operator.
Sometimes, no result is required, and the items are run in a loop simply for
some side-effect of the body.
foreach my $item ( @ITEMS ) {
FUNC( $item );
}
To avoid having to collect a potentially-large set of results only to throw
them away, the C<fmap_void> function variant of the C<fmap> family yields a
Future that completes with no result after all the items are complete.
my $f = fmap_void {
my $item = shift;
F_FIRST( $item )
} foreach => \@ITEMS, concurrent => 10;
=head1 AUTHOR
Paul Evans <leonerd@leonerd.org.uk>
=cut
( run in 1.028 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )