File Coverage

blib/lib/Future/PP.pm
Criterion Covered Total %
statement 575 583 98.6
branch 281 314 89.4
condition 140 171 81.8
subroutine 75 75 100.0
pod 0 48 0.0
total 1071 1191 89.9


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, 2011-2022 -- leonerd@leonerd.org.uk
5              
6             package Future::PP 0.52;
7              
8 33     33   423 use v5.14;
  33         124  
9 33     33   206 use warnings;
  33         60  
  33         2202  
10 33     33   184 no warnings 'recursion'; # Disable the "deep recursion" warning
  33         73  
  33         2406  
11              
12             our @ISA = qw( Future::_base );
13              
14 33     33   242 use Carp qw(); # don't import croak
  33         124  
  33         1305  
15 33     33   187 use List::Util 1.29 qw( pairs pairkeys );
  33         823  
  33         3102  
16 33     33   271 use Scalar::Util qw( weaken blessed reftype );
  33         122  
  33         2299  
17 33     33   187 use Time::HiRes qw( gettimeofday );
  33         83  
  33         298  
18              
19             our @CARP_NOT = qw( Future Future::_base Future::Utils );
20              
21 33     33   3705 use constant DEBUG => !!$ENV{PERL_FUTURE_DEBUG};
  33         74  
  33         3168  
22              
23 33     33   188 use constant STRICT => !!$ENV{PERL_FUTURE_STRICT};
  33         61  
  33         3465  
24              
25             # Callback flags
26             use constant {
27 33         4907 CB_DONE => 1<<0, # Execute callback on done
28             CB_FAIL => 1<<1, # Execute callback on fail
29             CB_CANCEL => 1<<2, # Execute callback on cancellation
30              
31             CB_SELF => 1<<3, # Pass $self as first argument
32             CB_RESULT => 1<<4, # Pass result/failure as a list
33              
34             CB_SEQ_ONDONE => 1<<5, # Sequencing on success (->then)
35             CB_SEQ_ONFAIL => 1<<6, # Sequencing on failure (->else)
36              
37             CB_SEQ_IMDONE => 1<<7, # $code is in fact immediate ->done result
38             CB_SEQ_IMFAIL => 1<<8, # $code is in fact immediate ->fail result
39              
40             CB_SEQ_STRICT => 1<<9, # Complain if $code didn't return a Future
41 33     33   193 };
  33         68  
42              
43 33     33   200 use constant CB_ALWAYS => CB_DONE|CB_FAIL|CB_CANCEL;
  33         182  
  33         199391  
44              
45             sub _shortmess
46             {
47 6     6   1031 my $at = Carp::shortmess( $_[0] );
48 6         23 chomp $at; $at =~ s/\.$//;
  6         35  
49 6         22 return $at;
50             }
51              
52             sub _callable
53             {
54 483     483   868 my ( $cb ) = @_;
55 483 50 33     3783 defined $cb and ( reftype($cb) eq 'CODE' || overload::Method($cb, '&{}') );
56             }
57              
58             sub new
59             {
60 728     728 0 114602 my $proto = shift;
61             return bless {
62             ready => 0,
63             callbacks => [], # [] = [$type, ...]
64             ( DEBUG ?
65 728 100 66     5467 ( do { my $at = Carp::shortmess( "constructed" );
66             chomp $at; $at =~ s/\.$//;
67             constructed_at => $at } )
68             : () ),
69             ( $Future::TIMES ?
70             ( btime => [ gettimeofday ] )
71             : () ),
72             }, ( ref $proto || $proto );
73             }
74              
75             sub __selfstr
76             {
77 20     12   1466 my $self = shift;
78 20         72 my $str = "$self";
79 20 100       94 $str .= " (\"$self->{label}\")" if defined $self->{label};
80 20 100       248 $str .= " ($self->{constructed_at})" if defined $self->{constructed_at};
81 12         1292 return $str;
82             }
83              
84             my $GLOBAL_END;
85 33     33   76010 END { $GLOBAL_END = 1; }
86              
87             sub DESTROY_debug {
88 8     8 0 380 my $self = shift;
89 8 50       22 return if $GLOBAL_END;
90 8 100 66     69 return if $self->{ready} and ( $self->{reported} or !$self->{failure} );
      100        
91              
92 3         17 my $lost_at = join " line ", (caller)[1,2];
93             # We can't actually know the real line where the last reference was lost;
94             # a variable set to 'undef' or close of scope, because caller can't see it;
95             # the current op has already been updated. The best we can do is indicate
96             # 'near'.
97              
98 3 100 66     19 if( $self->{ready} and $self->{failure} ) {
    50          
99 1         3 warn "${\$self->__selfstr} was lost near $lost_at with an unreported failure of: " .
100 1         3 $self->{failure}[0] . "\n";
101             }
102             elsif( !$self->{ready} ) {
103 2         4 warn "${\$self->__selfstr} was lost near $lost_at before it was ready.\n";
  2         14  
104             }
105             }
106             *DESTROY = \&DESTROY_debug if DEBUG;
107              
108             sub is_ready
109             {
110 483     483 0 15038 my $self = shift;
111 483         1958 return $self->{ready};
112             }
113              
114             sub is_done
115             {
116 79     79 0 160 my $self = shift;
117 79   66     846 return $self->{ready} && !$self->{failure} && !$self->{cancelled};
118             }
119              
120             sub is_failed
121             {
122 9     9 0 44 my $self = shift;
123 9   100     99 return $self->{ready} && !!$self->{failure}; # boolify
124             }
125              
126             sub is_cancelled
127             {
128 42     42 0 1607 my $self = shift;
129 42         223 return $self->{cancelled};
130             }
131              
132             sub state
133             {
134 8     8 0 19 my $self = shift;
135             return !$self->{ready} ? "pending" :
136             DEBUG ? $self->{ready_at} :
137             $self->{failure} ? "failed" :
138 8 100       1043 $self->{cancelled} ? "cancelled" :
    100          
    100          
139             "done";
140             }
141              
142             sub _mark_ready
143             {
144 565     565   928 my $self = shift;
145 565         981 $self->{ready} = 1;
146 565         750 $self->{ready_at} = _shortmess $_[0] if DEBUG;
147              
148 565 100       1313 if( $Future::TIMES ) {
149 4         21 $self->{rtime} = [ gettimeofday ];
150             }
151              
152 565         1065 delete $self->{on_cancel};
153 565   66     858 $_->[0] and $_->[0]->_revoke_on_cancel( $_->[1] ) for @{ $self->{revoke_when_ready} };
  565         2715  
154 565         5269 delete $self->{revoke_when_ready};
155              
156 565 100       1460 my $callbacks = delete $self->{callbacks} or return;
157              
158 560         975 my $cancelled = $self->{cancelled};
159 560         984 my $fail = defined $self->{failure};
160 560   100     1712 my $done = !$fail && !$cancelled;
161              
162 341         790 my @result = $done ? @{ $self->{result} } :
163 560 100       1374 $fail ? @{ $self->{failure} } :
  104 100       283  
164             ();
165              
166 560         1611 foreach my $cb ( @$callbacks ) {
167 339         716 my ( $flags, $code ) = @$cb;
168 339   66     934 my $is_future = blessed( $code ) && $code->isa( "Future" );
169              
170 339 100 100     1388 next if $done and not( $flags & CB_DONE );
171 299 100 100     880 next if $fail and not( $flags & CB_FAIL );
172 296 100 100     964 next if $cancelled and not( $flags & CB_CANCEL );
173              
174 264 100       617 $self->{reported} = 1 if $fail;
175              
176 264 100       730 if( $is_future ) {
    100          
177 23 100       128 $done ? $code->done( @result ) :
    100          
178             $fail ? $code->fail( @result ) :
179             $code->cancel;
180             }
181             elsif( $flags & (CB_SEQ_ONDONE|CB_SEQ_ONFAIL) ) {
182 60         157 my ( undef, undef, $fseq ) = @$cb;
183 60 100       155 if( !$fseq ) { # weaken()ed; it might be gone now
184             # This warning should always be printed, even not in DEBUG mode.
185             # It's always an indication of a bug
186 2         6 Carp::carp "${\$self->__selfstr} lost a sequence Future";
  2         11  
187 2         31 next;
188             }
189              
190 58         125 my $f2;
191 58 100 100     354 if( $done and $flags & CB_SEQ_ONDONE or
      100        
      100        
192             $fail and $flags & CB_SEQ_ONFAIL ) {
193              
194 52 100       185 if( $flags & CB_SEQ_IMDONE ) {
    100          
195 2         10 $fseq->done( @$code );
196 2         10 next;
197             }
198             elsif( $flags & CB_SEQ_IMFAIL ) {
199 2         10 $fseq->fail( @$code );
200 2         9 next;
201             }
202              
203 48 100       180 my @args = (
    100          
204             ( $flags & CB_SELF ? $self : () ),
205             ( $flags & CB_RESULT ? @result : () ),
206             );
207              
208 48 100       96 unless( eval { $f2 = $code->( @args ); 1 } ) {
  48         164  
  44         911  
209 4         45 $fseq->fail( $@ );
210 4         33 next;
211             }
212              
213 44 100 66     274 unless( blessed $f2 and $f2->isa( "Future" ) ) {
214             # Upgrade a non-Future result, or complain in strict mode
215 3 50       17 if( $flags & CB_SEQ_STRICT ) {
216 0         0 $fseq->fail( "Expected " . Future::CvNAME_FILE_LINE($code) . " to return a Future" );
217 0         0 next;
218             }
219 3         13 $f2 = Future->done( $f2 );
220             }
221              
222 44         125 $fseq->on_cancel( $f2 );
223             }
224             else {
225 6         30 $f2 = $self;
226             }
227              
228 50 100       135 if( $f2->is_ready ) {
229 30 50       167 $f2->on_ready( $fseq ) if !$f2->{cancelled};
230             }
231             else {
232 20         31 push @{ $f2->{callbacks} }, [ CB_DONE|CB_FAIL, $fseq ];
  20         84  
233 20         171 weaken( $f2->{callbacks}[-1][1] );
234             }
235             }
236             else {
237 181 100       709 $code->(
    100          
238             ( $flags & CB_SELF ? $self : () ),
239             ( $flags & CB_RESULT ? @result : () ),
240             );
241             }
242             }
243             }
244              
245             sub done
246             {
247 409     409 0 107764 my $self = shift;
248              
249 409 100       1072 if( ref $self ) {
250 316 100       1139 $self->{cancelled} and return $self;
251 313 100       2041 $self->{ready} and Carp::croak "${\$self->__selfstr} is already ".$self->state." and cannot be ->done";
  2         13  
252 311 50       778 $self->{subs} and Carp::croak "${\$self->__selfstr} is not a leaf Future, cannot be ->done";
  0         0  
253 311         797 $self->{result} = [ @_ ];
254 311         1016 $self->_mark_ready( "done" );
255             }
256             else {
257 93         298 $self = $self->new;
258 93         239 $self->{ready} = 1;
259 93         142 $self->{ready_at} = _shortmess "done" if DEBUG;
260 93         255 $self->{result} = [ @_ ];
261 93 100       358 if( $Future::TIMES ) {
262 1         5 $self->{rtime} = [ gettimeofday ];
263             }
264             }
265              
266 404         1313 return $self;
267             }
268              
269             sub fail
270             {
271 145     145 0 35564 my $self = shift;
272 145         1117 my ( $exception, @more ) = @_;
273              
274 145 100       461 if( ref $exception eq "Future::Exception" ) {
275 2         5 @more = ( $exception->category, $exception->details );
276 2         22 $exception = $exception->message;
277             }
278              
279 145 50       409 $exception or Carp::croak "$self ->fail requires an exception that is true";
280              
281 145 100       347 if( ref $self ) {
282 88 100       266 $self->{cancelled} and return $self;
283 87 100       257 $self->{ready} and Carp::croak "${\$self->__selfstr} is already ".$self->state." and cannot be ->fail'ed";
  2         8  
284 85 50       200 $self->{subs} and Carp::croak "${\$self->__selfstr} is not a leaf Future, cannot be ->fail'ed";
  0         0  
285 85         236 $self->{failure} = [ $exception, @more ];
286 85         289 $self->_mark_ready( "failed" );
287             }
288             else {
289 57         176 $self = $self->new;
290 57         137 $self->{ready} = 1;
291 57         107 $self->{ready_at} = _shortmess "failed" if DEBUG;
292 57         197 $self->{failure} = [ $exception, @more ];
293 57 100       189 if( $Future::TIMES ) {
294 1         4 $self->{rtime} = [ gettimeofday ];
295             }
296             }
297              
298 142         2004 return $self;
299             }
300              
301             sub on_cancel
302             {
303 338     338 0 4776 my $self = shift;
304 338         659 my ( $code ) = @_;
305              
306 338   66     1397 my $is_future = blessed( $code ) && $code->isa( "Future" );
307 338 50 66     1077 $is_future or _callable( $code ) or
308             Carp::croak "Expected \$code to be callable or a Future in ->on_cancel";
309              
310 338 100       935 $self->{ready} and return $self;
311              
312 315         521 push @{ $self->{on_cancel} }, $code;
  315         841  
313 315 100       709 if( $is_future ) {
314 219         310 push @{ $code->{revoke_when_ready} }, my $r = [ $self, \$self->{on_cancel}[-1] ];
  219         4144  
315 219         504 weaken( $r->[0] );
316 219         526 weaken( $r->[1] );
317             }
318              
319 315         662 return $self;
320             }
321              
322             # An optimised version for Awaitable role
323             sub AWAIT_ON_CANCEL
324             {
325 1     1 0 15 my $self = shift;
326 1         3 my ( $code ) = @_;
327              
328 1         3 push @{ $self->{on_cancel} }, $code;
  1         4  
329             }
330              
331             sub AWAIT_CHAIN_CANCEL
332             {
333 1     1 0 10 my $self = shift;
334 1         4 my ( $f2 ) = @_;
335              
336 1         3 push @{ $self->{on_cancel} }, $f2;
  1         3  
337 1         3 push @{ $f2->{revoke_when_ready} }, my $r = [ $self, \$self->{on_cancel}[-1] ];
  1         5  
338 1         3 weaken( $r->[0] );
339 1         3 weaken( $r->[1] );
340             }
341              
342             sub _revoke_on_cancel
343             {
344 193     193   342 my $self = shift;
345 193         370 my ( $ref ) = @_;
346              
347 193         343 undef $$ref;
348 193         442 $self->{empty_on_cancel_slots}++;
349              
350 193 100       596 my $on_cancel = $self->{on_cancel} or return;
351              
352             # If the list is nontrivally large and over half-empty / under half-full, compact it
353 172 100 100     784 if( @$on_cancel >= 8 and $self->{empty_on_cancel_slots} >= 0.5 * @$on_cancel ) {
354             # We can't grep { defined } because that will break all the existing SCALAR refs
355 3         7 my $idx = 0;
356 3         9 while( $idx < @$on_cancel ) {
357 175 100       401 defined $on_cancel->[$idx] and $idx++, next;
358 88         209 splice @$on_cancel, $idx, 1, ();
359             }
360 3         11 $self->{empty_on_cancel_slots} = 0;
361             }
362             }
363              
364             sub on_ready
365             {
366 177     177 0 15353 my $self = shift;
367 177         1890 my ( $code ) = @_;
368              
369 177   66     544 my $is_future = blessed( $code ) && $code->isa( "Future" );
370 177 50 66     623 $is_future or _callable( $code ) or
371             Carp::croak "Expected \$code to be callable or a Future in ->on_ready";
372              
373 177 100       489 if( $self->{ready} ) {
374 40         82 my $fail = defined $self->{failure};
375 40   100     156 my $done = !$fail && !$self->{cancelled};
376              
377 40 100       137 $self->{reported} = 1 if $fail;
378              
379 24         132 $is_future ? ( $done ? $code->done( @{ $self->{result} } ) :
380 40 100       174 $fail ? $code->fail( @{ $self->{failure} } ) :
  8 100       66  
    100          
381             $code->cancel )
382             : $code->( $self );
383             }
384             else {
385 137         215 push @{ $self->{callbacks} }, [ CB_ALWAYS|CB_SELF, $self->wrap_cb( on_ready => $code ) ];
  137         566  
386             }
387              
388 177         748 return $self;
389             }
390              
391             # An optimised version for Awaitable role
392             sub AWAIT_ON_READY
393             {
394 1     1 0 14 my $self = shift;
395 1         3 my ( $code ) = @_;
396 1         2 push @{ $self->{callbacks} }, [ CB_ALWAYS|CB_SELF, $self->wrap_cb( on_ready => $code ) ];
  1         6  
397             }
398              
399             sub result
400             {
401 97     97 0 6432 my $self = shift;
402             $self->{ready} or
403 97 100       401 Carp::croak( "${\$self->__selfstr} is not yet ready" );
  1         4  
404 96 100       323 if( my $failure = $self->{failure} ) {
405 11         29 $self->{reported} = 1;
406 11         65 my $exception = $failure->[0];
407 11 100       47 $exception = Future::Exception->new( @$failure ) if @$failure > 1;
408 11 100 100     1652 !ref $exception && $exception =~ m/\n$/ ? CORE::die $exception : Carp::croak $exception;
409             }
410 85 100       233 $self->{cancelled} and Carp::croak "${\$self->__selfstr} was cancelled";
  2         25  
411 83 100       417 return $self->{result}->[0] unless wantarray;
412 39         61 return @{ $self->{result} };
  39         324  
413             }
414              
415             sub get
416             {
417 10     10 0 111 my $self = shift;
418 10 100       60 $self->await unless $self->{ready};
419 9         32 return $self->result;
420             }
421              
422             sub await
423             {
424 4     4 0 35 my $self = shift;
425 4 100       23 return $self if $self->{ready};
426 1         173 Carp::croak "$self is not yet complete and does not provide ->await";
427             }
428              
429             sub on_done
430             {
431 89     89 0 637 my $self = shift;
432 89         191 my ( $code ) = @_;
433              
434 89   66     316 my $is_future = blessed( $code ) && $code->isa( "Future" );
435 89 50 66     1402 $is_future or _callable( $code ) or
436             Carp::croak "Expected \$code to be callable or a Future in ->on_done";
437              
438 89 100       264 if( $self->{ready} ) {
439 27 100 100     126 return $self if $self->{failure} or $self->{cancelled};
440              
441 14         76 $is_future ? $code->done( @{ $self->{result} } )
442 15 100       37 : $code->( @{ $self->{result} } );
  1         6  
443             }
444             else {
445 62         101 push @{ $self->{callbacks} }, [ CB_DONE|CB_RESULT, $self->wrap_cb( on_done => $code ) ];
  62         192  
446             }
447              
448 77         195 return $self;
449             }
450              
451             sub failure
452             {
453 144     144 0 696 my $self = shift;
454 144 100       376 $self->await unless $self->{ready};
455 144 100       403 return unless $self->{failure};
456 86         198 $self->{reported} = 1;
457 86 100       562 return $self->{failure}->[0] if !wantarray;
458 16         26 return @{ $self->{failure} };
  16         117  
459             }
460              
461             sub on_fail
462             {
463 88     88 0 527 my $self = shift;
464 88         162 my ( $code ) = @_;
465              
466 88   66     346 my $is_future = blessed( $code ) && $code->isa( "Future" );
467 88 50 66     273 $is_future or _callable( $code ) or
468             Carp::croak "Expected \$code to be callable or a Future in ->on_fail";
469              
470 88 100       228 if( $self->{ready} ) {
471 30 100       89 return $self if not $self->{failure};
472 12         33 $self->{reported} = 1;
473              
474 10         36 $is_future ? $code->fail( @{ $self->{failure} } )
475 12 100       36 : $code->( @{ $self->{failure} } );
  2         11  
476             }
477             else {
478 58         99 push @{ $self->{callbacks} }, [ CB_FAIL|CB_RESULT, $self->wrap_cb( on_fail => $code ) ];
  58         139  
479             }
480              
481 70         144 return $self;
482             }
483              
484             sub cancel
485             {
486 124     124 0 14426 my $self = shift;
487              
488 124 100       383 return $self if $self->{ready};
489              
490 116         264 $self->{cancelled}++;
491 116         240 my $on_cancel = delete $self->{on_cancel};
492 116 100       440 foreach my $code ( $on_cancel ? reverse @$on_cancel : () ) {
493 61 100       193 defined $code or next;
494 48   66     224 my $is_future = blessed( $code ) && $code->isa( "Future" );
495 48 100       235 $is_future ? $code->cancel
496             : $code->( $self );
497             }
498 116         448 $self->_mark_ready( "cancel" );
499              
500 116         436 return $self;
501             }
502              
503             my $make_donecatchfail_sub = sub {
504             my ( $with_f, $done_code, $fail_code, @catch_list ) = @_;
505              
506             my $func = (caller 1)[3];
507             $func =~ s/^.*:://;
508              
509             !$done_code or _callable( $done_code ) or
510             Carp::croak "Expected \$done_code to be callable in ->$func";
511             !$fail_code or _callable( $fail_code ) or
512             Carp::croak "Expected \$fail_code to be callable in ->$func";
513              
514             my %catch_handlers = @catch_list;
515             _callable( $catch_handlers{$_} ) or
516             Carp::croak "Expected catch handler for '$_' to be callable in ->$func"
517             for keys %catch_handlers;
518              
519             sub {
520             my $self = shift;
521             my @maybe_self = $with_f ? ( $self ) : ();
522              
523             if( !$self->{failure} ) {
524             return $self unless $done_code;
525             return $done_code->( @maybe_self, @{ $self->{result} } );
526             }
527             else {
528             my $name = $self->{failure}[1];
529             if( defined $name and $catch_handlers{$name} ) {
530             return $catch_handlers{$name}->( @maybe_self, @{ $self->{failure} } );
531             }
532             return $self unless $fail_code;
533             return $fail_code->( @maybe_self, @{ $self->{failure} } );
534             }
535             };
536             };
537              
538             sub _sequence
539             {
540 113     113   230 my $f1 = shift;
541 113         272 my ( $code, $flags ) = @_;
542              
543 113         191 $flags |= CB_SEQ_STRICT if STRICT;
544              
545             # For later, we might want to know where we were called from
546 113         206 my $level = 1;
547 113         804 $level++ while (caller $level)[0] eq "Future::_base";
548 113         464 my $func = (caller $level)[3];
549 113         809 $func =~ s/^.*:://;
550              
551 113 50 66     499 $flags & (CB_SEQ_IMDONE|CB_SEQ_IMFAIL) or _callable( $code ) or
552             Carp::croak "Expected \$code to be callable in ->$func";
553              
554 113 100       293 if( !defined wantarray ) {
555 4         1045 Carp::carp "Calling ->$func in void context";
556             }
557              
558 113 100       439 if( $f1->is_ready ) {
559             # Take a shortcut
560             return $f1 if $f1->is_done and not( $flags & CB_SEQ_ONDONE ) or
561 40 100 100     135 $f1->{failure} and not( $flags & CB_SEQ_ONFAIL );
      100        
      100        
562              
563 37 100       201 if( $flags & CB_SEQ_IMDONE ) {
    100          
564 2         10 return Future->done( @$code );
565             }
566             elsif( $flags & CB_SEQ_IMFAIL ) {
567 2         11 return Future->fail( @$code );
568             }
569              
570             my @args = (
571             ( $flags & CB_SELF ? $f1 : () ),
572 16         38 ( $flags & CB_RESULT ? $f1->is_done ? @{ $f1->{result} } :
573 33 100       147 $f1->{failure} ? @{ $f1->{failure} } :
  4 50       17  
    100          
    100          
574             () : () ),
575             );
576              
577 33         58 my $fseq;
578 33 100       66 unless( eval { $fseq = $code->( @args ); 1 } ) {
  33         101  
  31         141  
579 2         25 return Future->fail( $@ );
580             }
581              
582 31 100 66     217 unless( blessed $fseq and $fseq->isa( "Future" ) ) {
583             # Upgrade a non-Future result, or complain in strict mode
584 8 50       34 $flags & CB_SEQ_STRICT and
585             return Future->fail( "Expected " . Future::CvNAME_FILE_LINE($code) . " to return a Future" );
586              
587 8         24 $fseq = $f1->new->done( $fseq );
588             }
589              
590 31         192 return $fseq;
591             }
592              
593 73         199 my $fseq = $f1->new;
594 73         290 $fseq->on_cancel( $f1 );
595              
596             # TODO: if anyone cares about the op name, we might have to synthesize it
597             # from $flags
598 73 100       443 $code = $f1->wrap_cb( sequence => $code ) unless $flags & (CB_SEQ_IMDONE|CB_SEQ_IMFAIL);
599              
600 73         174 push @{ $f1->{callbacks} }, [ CB_DONE|CB_FAIL|$flags, $code, $fseq ];
  73         250  
601 73         189 weaken( $f1->{callbacks}[-1][2] );
602              
603 73         375 return $fseq;
604             }
605              
606             sub then
607             {
608 50     50 0 348 my $self = shift;
609 50         80 my $done_code = shift;
610 50 100       178 my $fail_code = ( @_ % 2 ) ? pop : undef;
611 50         105 my @catch_list = @_;
612              
613 50 100 100     352 if( $done_code and !@catch_list and !$fail_code ) {
      100        
614 43         246 return $self->_sequence( $done_code, CB_SEQ_ONDONE|CB_RESULT );
615             }
616              
617             # Complex
618 7         21 return $self->_sequence( $make_donecatchfail_sub->(
619             0, $done_code, $fail_code, @catch_list,
620             ), CB_SEQ_ONDONE|CB_SEQ_ONFAIL|CB_SELF );
621             }
622              
623             sub then_done
624             {
625 3     3 0 18 my $self = shift;
626 3         11 my ( @result ) = @_;
627 3         12 return $self->_sequence( \@result, CB_SEQ_ONDONE|CB_SEQ_IMDONE );
628             }
629              
630             sub then_fail
631             {
632 3     3 0 20 my $self = shift;
633 3         11 my ( @failure ) = @_;
634 3         10 return $self->_sequence( \@failure, CB_SEQ_ONDONE|CB_SEQ_IMFAIL );
635             }
636              
637             sub else
638             {
639 15     15 0 168 my $self = shift;
640 15         43 my ( $fail_code ) = @_;
641              
642 15         53 return $self->_sequence( $fail_code, CB_SEQ_ONFAIL|CB_RESULT );
643             }
644              
645             sub else_done
646             {
647 3     3 0 18 my $self = shift;
648 3         11 my ( @result ) = @_;
649 3         11 return $self->_sequence( \@result, CB_SEQ_ONFAIL|CB_SEQ_IMDONE );
650             }
651              
652             sub else_fail
653             {
654 3     3 0 18 my $self = shift;
655 3         10 my ( @failure ) = @_;
656 3         12 return $self->_sequence( \@failure, CB_SEQ_ONFAIL|CB_SEQ_IMFAIL );
657             }
658              
659             sub catch
660             {
661 5     5 0 43 my $self = shift;
662 5 100       17 my $fail_code = ( @_ % 2 ) ? pop : undef;
663 5         13 my @catch_list = @_;
664              
665 5         18 return $self->_sequence( $make_donecatchfail_sub->(
666             0, undef, $fail_code, @catch_list,
667             ), CB_SEQ_ONDONE|CB_SEQ_ONFAIL|CB_SELF );
668             }
669              
670             sub then_with_f
671             {
672 11     11 0 57 my $self = shift;
673 11         18 my $done_code = shift;
674 11 100       42 my $fail_code = ( @_ % 2 ) ? pop : undef;
675 11         27 my @catch_list = @_;
676              
677 11 100 66     81 if( $done_code and !@catch_list and !$fail_code ) {
      100        
678 3         17 return $self->_sequence( $done_code, CB_SEQ_ONDONE|CB_SELF|CB_RESULT );
679             }
680              
681 8         30 return $self->_sequence( $make_donecatchfail_sub->(
682             1, $done_code, $fail_code, @catch_list,
683             ), CB_SEQ_ONDONE|CB_SEQ_ONFAIL|CB_SELF );
684             }
685              
686             sub else_with_f
687             {
688 3     3 0 23 my $self = shift;
689 3         7 my ( $fail_code ) = @_;
690              
691 3         12 return $self->_sequence( $fail_code, CB_SEQ_ONFAIL|CB_SELF|CB_RESULT );
692             }
693              
694             sub catch_with_f
695             {
696 1     1 0 46 my $self = shift;
697 1 50       6 my $fail_code = ( @_ % 2 ) ? pop : undef;
698 1         3 my @catch_list = @_;
699              
700 1         4 return $self->_sequence( $make_donecatchfail_sub->(
701             1, undef, $fail_code, @catch_list,
702             ), CB_SEQ_ONDONE|CB_SEQ_ONFAIL|CB_SELF );
703             }
704              
705             sub followed_by
706             {
707 16     16 0 150 my $self = shift;
708 16         35 my ( $code ) = @_;
709              
710 16         81 return $self->_sequence( $code, CB_SEQ_ONDONE|CB_SEQ_ONFAIL|CB_SELF );
711             }
712              
713             sub without_cancel
714             {
715 3     3 0 334 my $self = shift;
716 3         10 my $new = $self->new;
717              
718             $self->on_ready( sub {
719 3     3   7 my $self = shift;
720 3 100       11 if( $self->{cancelled} ) {
    50          
721 1         4 $new->cancel;
722             }
723             elsif( $self->{failure} ) {
724 0         0 $new->fail( @{ $self->{failure} } );
  0         0  
725             }
726             else {
727 2         3 $new->done( @{ $self->{result} } );
  2         8  
728             }
729 3         27 });
730              
731 3         7 $new->{orig} = $self; # just to strongref it - RT122920
732 3     3   17 $new->on_ready( sub { undef $_[0]->{orig} } );
  3         22  
733              
734 3         10 return $new;
735             }
736              
737             # $self->{subs} is an even-sized list of *pairs*, ( $subf, $flags, $subf, $flags, ... )
738             # pairkeys @{ $self->{subs} } yields just the futures
739              
740             use constant {
741 33         94757 SUBFLAG_NO_CANCEL => (1<<0),
742 33     33   402 };
  33         81  
743              
744             sub _new_convergent
745             {
746 57     57   102 shift; # ignore this class
747 57         97 my ( $subs ) = @_;
748              
749 57         75 my @flaggedsubs;
750              
751 57         202 for ( my $i = 0; $i < @$subs; $i++ ) {
752 101         128 my $flags = 0;
753 101 100 66     302 $flags |= SUBFLAG_NO_CANCEL, $i++ if !blessed $subs->[$i] and $subs->[$i] eq "also";
754              
755 101         140 my $sub = $subs->[$i];
756 101 50 33     450 blessed $sub and $sub->isa( "Future" ) or Carp::croak "Expected a Future, got $sub";
757              
758 101         280 push @flaggedsubs, ( $sub, $flags );
759             }
760              
761             # Find the best prototype. Ideally anything derived if we can find one.
762 57         77 my $self;
763 57   66     371 ref($_) eq "Future" or $self = $_->new, last for pairkeys @flaggedsubs;
764              
765             # No derived ones; just have to be a basic class then
766 57   66     249 $self ||= Future->new;
767              
768 57         116 $self->{subs} = \@flaggedsubs;
769              
770 57         208 $self->on_cancel( \&_cancel_subs );
771              
772 57         186 @$subs = pairkeys @flaggedsubs;
773              
774 57         115 return $self;
775             }
776              
777             # This might be called by a DESTROY during global destruction so it should
778             # be as defensive as possible (see RT88967)
779             sub _cancel_subs
780             {
781 41     41   75 my $self = shift;
782 41 50       91 my $subs = $self->{subs} or return;
783              
784 41         325 foreach ( pairs @$subs ) {
785 72         176 my ( $sub, $flags ) = @$_;
786 72 100 66     454 $sub->cancel if !( $flags & SUBFLAG_NO_CANCEL ) and $sub and !$sub->{ready};
      100        
787             }
788             }
789              
790             sub wait_all
791             {
792 14     14 0 1036 my $class = shift;
793 14         38 my @subs = @_;
794              
795 14 100       45 unless( @subs ) {
796 2         9 my $self = $class->done;
797 2         6 $self->{subs} = [];
798 2         13 return $self;
799             }
800              
801 12         46 my $self = Future->_new_convergent( \@subs );
802              
803 12         24 my $pending = 0;
804 12   66     61 $_->{ready} or $pending++ for @subs;
805              
806             # Look for immediate ready
807 12 100       32 if( !$pending ) {
808 1         4 $self->{result} = [ @subs ];
809 1         6 $self->_mark_ready( "wait_all" );
810 1         5 return $self;
811             }
812              
813 11         41 weaken( my $weakself = $self );
814             my $sub_on_ready = sub {
815 15 50   15   58 return unless my $self = $weakself;
816              
817 15         33 $pending--;
818 15 100       84 $pending and return;
819              
820 10         17 $self->{result} = [ pairkeys @{ $self->{subs} } ];
  10         94  
821 10         45 $self->_mark_ready( "wait_all" );
822 11         91 };
823              
824 11         29 foreach my $sub ( @subs ) {
825 19 100       86 $sub->{ready} or $sub->on_ready( $sub_on_ready );
826             }
827              
828 11         49 return $self;
829             }
830              
831             sub wait_any
832             {
833 18     18 0 360 my $class = shift;
834 18         33 my @subs = @_;
835              
836 18 100       36 unless( @subs ) {
837 2         6 my $self = $class->fail( "Cannot ->wait_any with no subfutures" );
838 2         6 $self->{subs} = [];
839 2         8 return $self;
840             }
841              
842 16         60 my $self = Future->_new_convergent( \@subs );
843              
844             # Look for immediate ready
845 16         19 my $immediate_ready;
846 16         25 foreach my $sub ( @subs ) {
847 27 100 100     60 $sub->{ready} and !$sub->{cancelled} and $immediate_ready = $sub, last;
848             }
849              
850 16 100       25 if( $immediate_ready ) {
851 2         5 $self->_cancel_subs;
852              
853 2 50       6 if( $immediate_ready->{failure} ) {
854 0         0 $self->{failure} = [ @{ $immediate_ready->{failure} } ];
  0         0  
855             }
856             else {
857 2         2 $self->{result} = [ @{ $immediate_ready->{result} } ];
  2         6  
858             }
859 2         5 $self->_mark_ready( "wait_any" );
860 2         5 return $self;
861             }
862              
863 14         16 my $pending = 0;
864              
865 14         21 weaken( my $weakself = $self );
866             my $sub_on_ready = sub {
867 21 50   21   34 return unless my $self = $weakself;
868 21 100 100     79 return if $self->{result} or $self->{failure}; # don't recurse on child ->cancel
869              
870 15 100 100     54 return if --$pending and $_[0]->{cancelled};
871              
872 13 100       33 if( $_[0]->{cancelled} ) {
    100          
873 2         10 $self->{failure} = [ "All component futures were cancelled" ];
874             }
875             elsif( $_[0]->{failure} ) {
876 3         4 $self->{failure} = [ @{ $_[0]->{failure} } ];
  3         11  
877             }
878             else {
879 8         11 $self->{result} = [ @{ $_[0]->{result} } ];
  8         19  
880             }
881              
882 13         47 $self->_cancel_subs;
883              
884 13         44 $self->_mark_ready( "wait_any" );
885 14         54 };
886              
887 14         18 foreach my $sub ( @subs ) {
888             # No need to test $sub->{ready} since we know none of them are
889 25 100       45 next if $sub->{cancelled};
890 24         70 $sub->on_ready( $sub_on_ready );
891 24         30 $pending++;
892             }
893              
894 14         48 return $self;
895             }
896              
897             sub needs_all
898             {
899 18     18 0 550 my $class = shift;
900 18         90 my @subs = @_;
901              
902 18 100       51 unless( @subs ) {
903 2         10 my $self = $class->done;
904 2         7 $self->{subs} = [];
905 2         10 return $self;
906             }
907              
908 16         61 my $self = Future->_new_convergent( \@subs );
909              
910             # Look for immediate fail
911 16         31 my $immediate_failure;
912 16         35 foreach my $sub ( @subs ) {
913 30 100       95 $sub->{cancelled} and $immediate_failure = [ "A component future was cancelled" ], last;
914 29 100 100     85 $sub->{ready} and $sub->{failure} and $immediate_failure = $sub->{failure}, last;
915             }
916              
917 16 100       42 if( $immediate_failure ) {
918 2         8 $self->_cancel_subs;
919              
920 2         9 $self->{failure} = [ @$immediate_failure ];
921 2         7 $self->_mark_ready( "needs_all" );
922 2         8 return $self;
923             }
924              
925 14         22 my $pending = 0;
926 14   66     64 $_->{ready} or $pending++ for @subs;
927              
928             # Look for immediate done
929 14 100       36 if( !$pending ) {
930 1         3 $self->{result} = [ map { @{ $_->{result} } } @subs ];
  1         1  
  1         5  
931 1         4 $self->_mark_ready( "needs_all" );
932 1         4 return $self;
933             }
934              
935 13         50 weaken( my $weakself = $self );
936             my $sub_on_ready = sub {
937 24 50   24   70 return unless my $self = $weakself;
938 24 100 66     171 return if $self->{result} or $self->{failure}; # don't recurse on child ->cancel
939              
940 19 100       70 if( $_[0]->{cancelled} ) {
    100          
941 4         13 $self->{failure} = [ "A component future was cancelled" ];
942 4         29 $self->_cancel_subs;
943 4         51 $self->_mark_ready( "needs_all" );
944             }
945             elsif( $_[0]->{failure} ) {
946 4         8 $self->{failure} = [ @{ $_[0]->{failure} } ];
  4         12  
947 4         18 $self->_cancel_subs;
948 4         21 $self->_mark_ready( "needs_all" );
949             }
950             else {
951 11         15 $pending--;
952 11 100       100 $pending and return;
953              
954 4         8 $self->{result} = [ map { @{ $_->{result} } } pairkeys @{ $self->{subs} } ];
  10         14  
  10         25  
  4         29  
955 4         34 $self->_mark_ready( "needs_all" );
956             }
957 13         163 };
958              
959 13         33 foreach my $sub ( @subs ) {
960 26 50       97 $sub->{ready} or $sub->on_ready( $sub_on_ready );
961             }
962              
963 13         64 return $self;
964             }
965              
966             sub needs_any
967             {
968 15     15 0 369 my $class = shift;
969 15         28 my @subs = @_;
970              
971 15 100       31 unless( @subs ) {
972 2         8 my $self = $class->fail( "Cannot ->needs_any with no subfutures" );
973 2         5 $self->{subs} = [];
974 2         47 return $self;
975             }
976              
977 13         34 my $self = Future->_new_convergent( \@subs );
978              
979             # Look for immediate done
980 13         18 my $immediate_done;
981 13         14 my $pending = 0;
982 13         21 foreach my $sub ( @subs ) {
983 22 100 100     57 $sub->{ready} and !$sub->{failure} and !$sub->{cancelled} and $immediate_done = $sub, last;
      100        
984 21 100       44 $sub->{ready} or $pending++;
985             }
986              
987 13 100       24 if( $immediate_done ) {
988 1         1 foreach my $sub ( @subs ) {
989 2 50       6 $sub->{ready} ? $sub->{reported} = 1 : $sub->cancel;
990             }
991              
992 1         50 $self->{result} = [ @{ $immediate_done->{result} } ];
  1         4  
993 1         6 $self->_mark_ready( "needs_any" );
994 1         3 return $self;
995             }
996              
997             # Look for immediate fail
998 12         15 my $immediate_fail = 1;
999 12         18 foreach my $sub ( @subs ) {
1000 12 100       32 $sub->{ready} or $immediate_fail = 0, last;
1001             }
1002              
1003 12 100       60 if( $immediate_fail ) {
1004 1         3 $_->{reported} = 1 for @subs;
1005             # For consistency we'll pick the last one for the failure
1006 1         3 $self->{failure} = [ $subs[-1]->{failure} ];
1007 1         3 $self->_mark_ready( "needs_any" );
1008 1         2 return $self;
1009             }
1010              
1011 11         17 weaken( my $weakself = $self );
1012             my $sub_on_ready = sub {
1013 16 50   16   28 return unless my $self = $weakself;
1014 16 100 66     78 return if $self->{result} or $self->{failure}; # don't recurse on child ->cancel
1015              
1016 14 100 100     38 return if --$pending and $_[0]->{cancelled};
1017              
1018 12 100       32 if( $_[0]->{cancelled} ) {
    100          
1019 2         5 $self->{failure} = [ "All component futures were cancelled" ];
1020 2         7 $self->_mark_ready( "needs_any" );
1021             }
1022             elsif( $_[0]->{failure} ) {
1023 3 100       13 $pending and return;
1024              
1025 1         2 $self->{failure} = [ @{ $_[0]->{failure} } ];
  1         2  
1026 1         3 $self->_mark_ready( "needs_any" );
1027             }
1028             else {
1029 7         7 $self->{result} = [ @{ $_[0]->{result} } ];
  7         14  
1030 7         36 $self->_cancel_subs;
1031 7         22 $self->_mark_ready( "needs_any" );
1032             }
1033 11         92 };
1034              
1035 11         66 foreach my $sub ( @subs ) {
1036 19 100       59 $sub->{ready} or $sub->on_ready( $sub_on_ready );
1037             }
1038              
1039 11         36 return $self;
1040             }
1041              
1042             sub pending_futures
1043             {
1044 7     7 0 16713 my $self = shift;
1045 7 50       36 $self->{subs} or Carp::croak "Cannot call ->pending_futures on a non-convergent Future";
1046 7         30 return grep { not $_->{ready} } pairkeys @{ $self->{subs} };
  14         70  
  7         43  
1047             }
1048              
1049             sub ready_futures
1050             {
1051 7     7 0 22 my $self = shift;
1052 7 50       47 $self->{subs} or Carp::croak "Cannot call ->ready_futures on a non-convergent Future";
1053 7         13 return grep { $_->{ready} } pairkeys @{ $self->{subs} };
  14         61  
  7         56  
1054             }
1055              
1056             sub done_futures
1057             {
1058 9     9 0 42 my $self = shift;
1059 9 50       55 $self->{subs} or Carp::croak "Cannot call ->done_futures on a non-convergent Future";
1060 9 100 100     17 return grep { $_->{ready} and not $_->{failure} and not $_->{cancelled} } pairkeys @{ $self->{subs} };
  18         181  
  9         41  
1061             }
1062              
1063             sub failed_futures
1064             {
1065 4     4 0 472 my $self = shift;
1066 4 50       16 $self->{subs} or Carp::croak "Cannot call ->failed_futures on a non-convergent Future";
1067 4 50       8 return grep { $_->{ready} and $_->{failure} } pairkeys @{ $self->{subs} };
  8         52  
  4         20  
1068             }
1069              
1070             sub cancelled_futures
1071             {
1072 6     6 0 14 my $self = shift;
1073 6 50       26 $self->{subs} or Carp::croak "Cannot call ->cancelled_futures on a non-convergent Future";
1074 6 50       10 return grep { $_->{ready} and $_->{cancelled} } pairkeys @{ $self->{subs} };
  12         76  
  6         28  
1075             }
1076              
1077             sub btime
1078             {
1079 11     11 0 24 my $self = shift;
1080 11         57 return $self->{btime};
1081             }
1082              
1083             sub rtime
1084             {
1085 12     12 0 316 my $self = shift;
1086 12         52 return $self->{rtime};
1087             }
1088              
1089             sub set_label
1090             {
1091 6     6 0 56 my $self = shift;
1092 6         21 ( $self->{label} ) = @_;
1093 6         23 return $self;
1094             }
1095              
1096             sub label
1097             {
1098 1     1 0 3 my $self = shift;
1099 1         5 return $self->{label};
1100             }
1101              
1102             sub set_udata
1103             {
1104 1     1 0 5 my $self = shift;
1105 1         3 my ( $name, $value ) = @_;
1106 1         4 $self->{"u_$name"} = $value;
1107 1         5 return $self;
1108             }
1109              
1110             sub udata
1111             {
1112 1     1 0 1 my $self = shift;
1113 1         2 my ( $name ) = @_;
1114 1         3 return $self->{"u_$name"};
1115             }
1116              
1117             0x55AA;