fixup start, add then::
Matt S Trout [Tue, 17 Jul 2012 22:54:40 +0000 (22:54 +0000)]
lib/Object/Remote/Future.pm
t/start_core.t [new file with mode: 0644]

index c5ac7ee..04bc251 100644 (file)
@@ -34,9 +34,6 @@ package start;
 sub AUTOLOAD {
   my $invocant = shift;
   my ($method) = our $AUTOLOAD =~ /^start::(.+)$/;
-  if (ref($invocant) eq 'ARRAY') {
-    return [ map $_->${\"start::${method}"}, @$invocant ];
-  }
   my $res;
   unless (eval { $res = $invocant->$method(@_); 1 }) {
     my $f = CPS::Future->new;
@@ -51,6 +48,25 @@ sub AUTOLOAD {
   return $res;
 }
 
+package then;
+
+sub AUTOLOAD {
+  my $invocant = shift;
+  my ($method) = our $AUTOLOAD =~ /^then::(.+)$/;
+  my @args = @_;
+  # Need two copies since if we're called on an already complete future
+  # $f will be freed immediately
+  my $ret = my $f = CPS::Future->new;
+  $invocant->on_fail(sub { $f->fail(@_); undef($f); });
+  $invocant->on_done(sub {
+    my ($obj) = @_;
+    my $next = $obj->${\"start::${method}"}(@args);
+    $next->on_done(sub { $f->done(@_); undef($f); });
+    $next->on_fail(sub { $f->fail(@_); undef($f); });
+  });
+  return $ret;
+}
+
 1;
 
 =head1 NAME
diff --git a/t/start_core.t b/t/start_core.t
new file mode 100644 (file)
index 0000000..31d5349
--- /dev/null
@@ -0,0 +1,78 @@
+use strictures 1;
+use Test::More;
+
+{
+  package S1S;
+
+  use Moo;
+
+  sub get_s2 {
+    S2S->new
+  }
+}
+
+{
+  package S1F;
+
+  use Object::Remote::Future;
+  use Moo;
+
+  our $C;
+
+  sub get_s2 {
+    future {
+      my $f = shift;
+      $C = sub { $f->done(S2F->new); undef($f); };
+      $f;
+    }
+  }
+}
+
+{
+  package S2S;
+
+  use Moo;
+
+  sub get_s3 { 'S3' }
+}
+
+{
+  package S2F;
+
+  use Object::Remote::Future;
+  use Moo;
+
+  our $C;
+
+  sub get_s3 {
+    future {
+      my $f = shift;
+      $C = sub { $f->done('S3'); undef($f); };
+      $f;
+    }
+  }
+}
+
+my $res;
+
+S1S->start::get_s2->then::get_s3->on_ready(sub { ($res) = $_[0]->get });
+
+is($res, 'S3', 'Synchronous code ok');
+
+undef($res);
+
+S1F->start::get_s2->then::get_s3->on_ready(sub { ($res) = $_[0]->get });
+
+ok(!$S2F::C, 'Second future not yet constructed');
+
+$S1F::C->();
+
+ok($S2F::C, 'Second future constructed after first future completed');
+
+ok(!$res, 'Nothing happened yet');
+
+$S2F::C->();
+
+is($res, 'S3', 'Asynchronous code ok');
+
+done_testing;