File Coverage

blib/lib/AnyEvent/Future.pm
Criterion Covered Total %
statement 61 61 100.0
branch 4 4 100.0
condition 2 3 66.6
subroutine 20 20 100.0
pod 6 7 85.7
total 93 95 97.8


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2014-2015 -- leonerd@leonerd.org.uk
5              
6             package AnyEvent::Future;
7              
8 4     4   95685 use strict;
  4         8  
  4         165  
9 4     4   19 use warnings;
  4         5  
  4         183  
10              
11             our $VERSION = '0.03';
12              
13 4     4   19 use base qw( Future );
  4         13  
  4         2827  
14             Future->VERSION( '0.05' ); # to respect subclassing
15              
16 4     4   38322 use Exporter 'import';
  4         10  
  4         235  
17             our @EXPORT_OK = qw(
18             as_future
19             as_future_cb
20             );
21              
22 4     4   1282 use AnyEvent;
  4         5351  
  4         2255  
23              
24             =head1 NAME
25              
26             C - use L with L
27              
28             =head1 SYNOPSIS
29              
30             use AnyEvent;
31             use AnyEvent::Future;
32              
33             my $future = AnyEvent::Future->new;
34              
35             some_async_function( ..., cb => sub { $future->done( @_ ) } );
36              
37             print Future->await_any(
38             $future,
39             AnyEvent::Future->new_timeout( after => 10 ),
40             )->get;
41              
42             Or
43              
44             use AnyEvent::Future qw( as_future_cb );
45              
46             print Future->await_any(
47             as_future_cb {
48             some_async_function( ..., cb => shift )
49             },
50             AnyEvent::Future->new_timeout( after => 10 ),
51             )->get;
52              
53             =head1 DESCRIPTION
54              
55             This subclass of L integrates with L, allowing the C
56             method to block until the future is ready. It allows C-using code to
57             be written that returns C instances, so that it can make full use of
58             C's abilities, including L, and also that modules using
59             it can provide a C-based asynchronous interface of their own.
60              
61             For a full description on how to use Futures, see the L documentation.
62              
63             =cut
64              
65             # Forward
66             sub as_future(&);
67              
68             =head1 CONSTRUCTORS
69              
70             =cut
71              
72             =head2 $f = AnyEvent::Future->new
73              
74             Returns a new leaf future instance, which will allow waiting for its result to
75             be made available, using the C method.
76              
77             =cut
78              
79             =head2 $f = AnyEvent::Future->new_delay( @args )
80              
81             =head2 $f = AnyEvent::Future->new_timeout( @args )
82              
83             Returns a new leaf future instance that will become ready at the time given by
84             the arguments, which will be passed to the C<< AnyEvent->timer >> method.
85              
86             C returns a future that will complete successfully at the alotted
87             time, whereas C returns a future that will fail with the message
88             C.
89              
90             =cut
91              
92             sub new_delay
93             {
94 1     1 1 12 shift;
95 1         3 my %args = @_;
96              
97             as_future {
98 1     1   1 my $f = shift;
99 1         10 AnyEvent->timer( %args, cb => sub { $f->done } );
  1         999283  
100 1         8 };
101             }
102              
103             sub new_timeout
104             {
105 1     1 1 1209 shift;
106 1         4 my %args = @_;
107              
108             as_future {
109 1     1   2 my $f = shift;
110 1         14 AnyEvent->timer( %args, cb => sub { $f->fail( "Timeout" ) } );
  1         999252  
111 1         8 };
112             }
113              
114             =head2 $f = AnyEvent::Future->from_cv( $cv )
115              
116             Returns a new leaf future instance that will become ready when the given
117             L instance is ready. The success or failure result of the
118             future will be the result passed to the condvar's C or C method.
119              
120             =cut
121              
122             sub from_cv
123             {
124 3     3 1 5610 my $class = shift;
125 3         7 my ( $cv ) = @_;
126              
127 3         18 my $f = $class->new;
128              
129 3         31 my $was_cb = $cv->cb;
130              
131             $cv->cb( sub {
132 3     3   840 my ( $cv ) = @_;
133 3         5 my @result;
134 3 100 66     5 eval { @result = $cv->recv; 1 } and $f->done( @result ) or
  3         15  
  2         41  
135             $f->fail( $@ );
136              
137 3 100       382 $was_cb->( @_ ) if $was_cb;
138 3         83 });
139              
140 3         19 return $f;
141             }
142              
143             =head1 METHODS
144              
145             =cut
146              
147             =head2 $cv = $f->as_cv
148              
149             Returns a new C instance that wraps the given future; it
150             will complete with success or failure when the future does.
151              
152             Note that because C<< AnyEvent::CondVar->croak >> takes only a single string
153             message for the argument, any subsequent failure semantics are lost from the
154             Future. To capture these as well, you may wish to use an C callback
155             or the C method, to obtain them.
156              
157             =cut
158              
159             sub as_cv
160             {
161 2     2 1 1545 my $self = shift;
162              
163 2         55 my $cv = AnyEvent->condvar;
164              
165 2     1   22 $self->on_done( sub { $cv->send( @_ ) } );
  1         43  
166 2     1   55 $self->on_fail( sub { $cv->croak( $_[0] ) } );
  1         42  
167              
168 2         29 return $cv;
169             }
170              
171             sub await
172             {
173 6     6 0 5920 my $self = shift;
174              
175 6         306 my $cv = AnyEvent->condvar;
176 6     6   445 $self->on_ready( sub { $cv->send } );
  6         5243  
177              
178 6         182 $cv->recv;
179             }
180              
181             =head1 UTILITY FUNCTIONS
182              
183             The following utility functions are exported as a convenience.
184              
185             =cut
186              
187             =head2 $f = as_future { CODE }
188              
189             Returns a new leaf future instance, which is also passed in to the block of
190             code. The code is called in scalar context, and its return value is stored on
191             the future. This will be deleted if the future is cancelled.
192              
193             $w = CODE->( $f )
194              
195             This utility is provided for the common case of wanting to wrap an C
196             function which will want to receive a callback function to inform of
197             completion, and which will return a watcher object reference that needs to be
198             stored somewhere.
199              
200             =cut
201              
202             sub as_future(&)
203             {
204 6     6 1 1627 my ( $code ) = @_;
205              
206 6         44 my $f = AnyEvent::Future->new;
207              
208 6         218 $f->{w} = $code->( $f );
209 6     1   3615 $f->on_cancel( sub { undef shift->{w} } );
  1         37  
210              
211 6         139 return $f;
212             }
213              
214             =head2 $f = as_future_cb { CODE }
215              
216             A futher shortcut to C, where the code is passed two callback
217             functions for C and C directly, avoiding boilerplate in the common
218             case for creating these closures capturing the future variable. In many cases
219             this can reduce the code block to a single line.
220              
221             $w = CODE->( $done_cb, $fail_cb )
222              
223             =cut
224              
225             sub as_future_cb(&)
226             {
227 2     2 1 31066 my ( $code ) = @_;
228              
229             &as_future( sub {
230 2     2   5 my $f = shift;
231 2         24 $code->( $f->done_cb, $f->fail_cb );
232 2         19 });
233             }
234              
235             =head1 EXAMPLES
236              
237             =head2 Wrapping watcher-style C functions
238              
239             The C utility provides an excellent wrapper to take the common
240             style of C function that returns a watcher object and takes a
241             completion callback, and turn it into a C that can be used or combined
242             with other C-based code. For example, the L function
243             called C performs in this style.
244              
245             use AnyEvent::Future qw( as_future_cb );
246             use AnyEvent::HTTP qw( http_get );
247              
248             my $url = ...;
249              
250             my $f = as_future_cb {
251             my ( $done_cb ) = @_;
252              
253             http_get $url, $done_cb;
254             };
255              
256             This could of course be easily wrapped by a convenient function to return
257             futures:
258              
259             sub http_get_future
260             {
261             my @args = @_;
262              
263             as_future_cb {
264             my ( $done_cb ) = @_;
265              
266             http_get @args, $done_cb;
267             }
268             }
269              
270             =head2 Using Cs as enhanced Cs
271              
272             While at first glance it may appear that a C instance is much like an
273             L, the greater set of convergence methods (such as
274             C or C), and the various utility functions (in
275             L) makes it possible to write the same style of code in a more
276             concise or powerful way.
277              
278             For example, rather than using the C C and C methods, a
279             set of C-returning functions can be converted into C,
280             combined using C, and converted back to a C again:
281              
282             my $cv = Future->needs_all(
283             Future::AnyEvent->from_cv( FUNC1() ),
284             Future::AnyEvent->from_cv( FUNC2() ),
285             ...
286             )->as_cv;
287              
288             my @results = $cv->recv;
289              
290             This would become yet more useful if, instead of functions that return
291             C, we were operating on functions that return Cs directly.
292             Because the C will cancel any still-pending futures the moment one
293             of them failed, we get a nice neat cancellation of outstanding work if one of
294             them fails, in a way that would be much harder without the Cs. For
295             example, using the C function from above:
296              
297             my $cv = Future->needs_all(
298             http_get_future( "http://url-1" ),
299             http_get_future( "http://url-2" ),
300             http_get_future( "https://url-third/secret" ),
301             )->as_cv;
302              
303             my @results = $cv->recv;
304              
305             In this case, the moment any of the HTTP GET functions fails, the ones that
306             are still pending are all cancelled (by dropping their cancellation watcher
307             object) and the overall C call throws an exception.
308              
309             Of course, there is no need to convert the outermost C into a
310             C; the full set of waiting semantics are implemented on these
311             instances, so instead you may simply call C on it to achieve the same
312             effect:
313              
314             my $f = Future->needs_all(
315             http_get_future( "http://url-1" ),
316             ...
317             );
318              
319             my @results = $f->get;
320              
321             This has other side advantages, such as the list-valued semantics of failures
322             that can provide additional information besides just the error message, and
323             propagation of cancellation requests.
324              
325             =cut
326              
327             =head1 TODO
328              
329             =over 4
330              
331             =item *
332              
333             Consider whether or not it would be considered "evil" to inject a new method
334             into L; namely by doing
335              
336             sub AnyEvent::CondVar::as_future { AnyEvent::Future->from_cv( shift ) }
337              
338             =back
339              
340             =head1 AUTHOR
341              
342             Paul Evans
343              
344             =cut
345              
346             0x55AA;