use CPS::Future;
-our @EXPORT = qw(future await_future);
+our @EXPORT = qw(future await_future await_all);
sub future (&) {
my $f = $_[0]->(CPS::Future->new);
return wantarray ? $f->get : ($f->get)[0];
}
+sub await_all {
+ await_future(CPS::Future->wait_all(@_));
+ map $_->get, @_;
+}
+
package start;
sub AUTOLOAD {
my $invocant = shift;
- my ($method) = our $AUTOLOAD =~ /([^:]+)$/;
- if (ref($invocant) eq 'ARRAY') {
- return [ map $_->${\"start::${method}"}, @$invocant ];
- }
+ my ($method) = our $AUTOLOAD =~ /^start::(.+)$/;
my $res;
unless (eval { $res = $invocant->$method(@_); 1 }) {
my $f = CPS::Future->new;
return $res;
}
-package await;
+package maybe::start;
sub AUTOLOAD {
my $invocant = shift;
- my ($method) = our $AUTOLOAD =~ /([^:]+)$/;
- my @invocants = (ref($invocant) eq 'ARRAY' ? @$invocant : $invocant);
- my @futures = map $_->${\"start::${method}"}, @$invocant;
- Object::Remote::Future::await_future(CPS::Future->needs_all(@futures));
- return map $_->get, @futures;
+ my ($method) = our $AUTOLOAD =~ /^maybe::start::(.+)$/;
+ $method = "start::${method}" if ((caller(1)||'') eq 'start');
+ $invocant->$method(@_);
+}
+
+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
+
+Object::Remote::Future - Asynchronous calling for L<Object::Remote>
+
+=head1 LAME
+
+Shipping prioritised over writing this part up. Blame mst.
+
+=cut