AnyEvent-Future

 view release on metacpan or  search on metacpan

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


   my $url = ...;

   my $f = as_future_cb {
      my ( $done_cb ) = @_;

      http_get $url, $done_cb;
   };

This could of course be easily wrapped by a convenient function to return
futures:

   sub http_get_future
   {
      my ( $url, @args ) = @_;

      as_future_cb {
         my ( $done_cb ) = @_;

         http_get $url, @args, $done_cb;
      }
   }

=head2 Using C<Future>s as enhanced C<CondVar>s

While at first glance it may appear that a C<Future> instance is much like an
L<AnyEvent::CondVar>, the greater set of convergence methods (such as
C<needs_all> or C<needs_any>), and the various utility functions (in
L<Future::Utils>) makes it possible to write the same style of code in a more
concise or powerful way.

For example, rather than using the C<CondVar> C<begin> and C<end> methods, a
set of C<CondVar>-returning functions can be converted into C<Futures>,
combined using C<needs_all>, and converted back to a C<CondVar> again:

   my $cv = Future->needs_all(
      Future::AnyEvent->from_cv( FUNC1() ),
      Future::AnyEvent->from_cv( FUNC2() ),
      ...
   )->as_cv;

   my @results = $cv->recv;

This would become yet more useful if, instead of functions that return
C<CondVars>, we were operating on functions that return C<Future>s directly.
Because the C<needs_all> will cancel any still-pending futures the moment one
of them failed, we get a nice neat cancellation of outstanding work if one of
them fails, in a way that would be much harder without the C<Future>s. For
example, using the C<http_get_future> function from above:

   my $cv = Future->needs_all(
      http_get_future( "http://url-1" ),
      http_get_future( "http://url-2" ),
      http_get_future( "https://url-third/secret" ),
   )->as_cv;

   my @results = $cv->recv;

In this case, the moment any of the HTTP GET functions fails, the ones that
are still pending are all cancelled (by dropping their cancellation watcher
object) and the overall C<recv> call throws an exception.

Of course, there is no need to convert the outermost C<Future> into a
C<CondVar>; the full set of waiting semantics are implemented on these
instances, so instead you may simply call C<get> on it to achieve the same
effect:

   my $f = Future->needs_all(
      http_get_future( "http://url-1" ),
      ...
   );

   my @results = $f->get;

This has other side advantages, such as the list-valued semantics of failures
that can provide additional information besides just the error message, and
propagation of cancellation requests.

=cut

=head1 TODO

=over 4

=item *

Consider whether or not it would be considered "evil" to inject a new method
into L<AnyEvent::CondVar>; namely by doing

   sub AnyEvent::CondVar::as_future { AnyEvent::Future->from_cv( shift ) }

=back

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>

=cut

0x55AA;



( run in 0.725 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )