Skip Menu |

This queue is for tickets about the future CPAN distribution.

Report information
The Basics
Id: 84187
Status: resolved
Priority: 0/
Queue: future

People
Owner: Nobody in particular
Requestors: TOSHIOITO [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.11
Fixed in: 0.12



Subject: needs_all() throws an exception when immediate failed subfutures are given
Future->needs_all(@subfutures) method throws an exception when immediate failed Futures are included in @subfutures. Future->needs_all() should accept immediate failed subfutures without exceptions. I ran the following test: use strict; use warnings; use Test::More; use Future 0.11; foreach my $method (qw(wait_all wait_any needs_all needs_any)) { foreach my $done_first (0,1) { my $msg = "$method, done_first = $done_first"; my @done_subs = map { Future->new->done($_) } 1..5; my @fail_subs = map { Future->new->fail("failure $_") } 1..5; my @subs = $done_first ? (@done_subs, @fail_subs) : (@fail_subs, @done_subs); my $f = eval { Future->$method(@subs); pass($msg); }; if($@) { fail($msg); diag("Exception: $@"); } } } done_testing(); Then the result was: ok 1 - wait_all, done_first = 0 ok 2 - wait_all, done_first = 1 ok 3 - wait_any, done_first = 0 ok 4 - wait_any, done_first = 1 not ok 5 - needs_all, done_first = 0 # Failed test 'needs_all, done_first = 0' # at test.pl line 19. # Exception: failure 1 at test.pl line 15. not ok 6 - needs_all, done_first = 1 # Failed test 'needs_all, done_first = 1' # at test.pl line 19. # Exception: failure 1 at test.pl line 15. ok 7 - needs_any, done_first = 0 ok 8 - needs_any, done_first = 1 1..8 # Looks like you failed 2 tests of 8.
On Mon Mar 25 01:09:05 2013, TOSHIOITO wrote: Show quoted text
> Future->needs_all(@subfutures) method throws an exception when > immediate failed Futures are included in @subfutures. > > Future->needs_all() should accept immediate failed subfutures without > exceptions.
Ah yes; indeed that one looks like it should be fixed. -- Paul Evans
The immediate issue is now fixed by theabove patch. Though I think I'll neaten up the code a little further also, to more efficiently handle dependent Futures partly or entirely based on immediate Futures. -- Paul Evans
Subject: rt84187.patch
=== modified file 'lib/Future.pm' --- lib/Future.pm 2013-03-22 20:10:09 +0000 +++ lib/Future.pm 2013-03-26 15:40:36 +0000 @@ -906,6 +906,15 @@ my $self = Future->_new_dependent( \@subs ); + # Look for immediate fails + foreach my $sub ( @subs ) { + next unless $sub->is_ready and $sub->failure; + + $self->{failure} = [ $sub->failure ]; + $self->_mark_ready; + return $self; + } + weaken( my $weakself = $self ); my $sub_on_ready = sub { return if $_[0]->is_cancelled; === modified file 't/12needs_all.t' --- t/12needs_all.t 2013-03-14 17:10:13 +0000 +++ t/12needs_all.t 2013-03-26 15:40:36 +0000 @@ -90,18 +90,14 @@ # immediately done { - my $f1 = Future->new->done; - - my $future = Future->needs_all( $f1 ); + my $future = Future->needs_all( Future->new->done ); ok( $future->is_ready, '$future of already-done sub already ready' ); } # immediately fails { - my $f1 = Future->new->fail( "Failure" ); - - my $future = Future->needs_all( $f1 ); + my $future = Future->needs_all( Future->new->fail("F1"), Future->new->done ); ok( $future->is_ready, '$future of already-failed sub already ready' ); } === modified file 't/13needs_any.t' --- t/13needs_any.t 2013-03-14 17:10:13 +0000 +++ t/13needs_any.t 2013-03-26 15:40:36 +0000 @@ -125,18 +125,14 @@ # immediately done { - my $f1 = Future->new->done; - - my $future = Future->needs_any( $f1 ); + my $future = Future->needs_any( Future->new->fail("F1"), Future->new->done ); ok( $future->is_ready, '$future of already-done sub already ready' ); } # immediately fails { - my $f1 = Future->new->fail( "Failure" ); - - my $future = Future->needs_any( $f1 ); + my $future = Future->needs_any( Future->new->fail("F1") ); ok( $future->is_ready, '$future of already-failed sub already ready' ); }
Thank you for fixing!