use strictures 1;
use Object::Remote::Connector::STDIO;
use Object::Remote;
+use CPS::Future;
#$Object::Remote::Connection::DEBUG = 1;
my $loop = Object::Remote->current_loop;
-$c->on_close(sub { $loop->stop });
+my $f = CPS::Future->new;
+
+$f->on_ready(sub { $loop->stop });
+
+$c->on_close($f);
print { $c->send_to_fh } "Shere\n";
use Object::Remote::MiniLoop;
use Object::Remote::Proxy;
use Scalar::Util qw(weaken blessed);
+use Object::Remote::Future;
use Module::Runtime qw(use_module);
use Moo;
die "No id supplied and no class either" unless $args->{class};
ref($_) eq 'HASH' and $_ = [ %$_ ] for $args->{args};
$self->_set_id(
- $self->_await(
+ await_future(
$self->connection->send(
class_call => $args->{class}, 0,
$args->{constructor}||'new', @{$args->{args}||[]}
sub call {
my ($self, $method, @args) = @_;
- $self->_await(
- $self->connection->send(call => $self->id, wantarray, $method, @args)
- );
+ my $w = wantarray;
+ future {
+ $self->connection->send(call => $self->id, $w, $method, @args)
+ };
}
sub call_discard {
$self->connection->send_discard(call_free => $self->id, $method, @args);
}
-sub _await {
- my ($self, $future) = @_;
- my $loop = $self->current_loop;
- $future->on_ready(sub { $loop->stop });
- $loop->run;
- wantarray ? $future->get : ($future->get)[0];
-}
-
sub DEMOLISH {
my ($self, $gd) = @_;
return if $gd or $self->disarmed_free;
package Object::Remote::Connection;
-use CPS::Future;
+use Object::Remote::Future;
use Object::Remote::Null;
use Object::Remote;
use IO::Handle;
$self->_receive($1);
}
} else {
- $self->on_close->();
+ $self->on_close->done();
}
}
sub _invoke {
my ($self, $future, $local, $ctx, $method, @args) = @_;
+ if ($method =~ /^start::/) {
+ my $f = $local->$method(@args);
+ $f->on_done(sub { undef($f); $future->done(@_) });
+ $f->on_fail(sub { undef($f); $future->fail(@_) });
+ return;
+ }
my $do = sub { $local->$method(@args) };
eval {
$future->done(
--- /dev/null
+package Object::Remote::Future;
+
+use strict;
+use warnings;
+use base qw(Exporter);
+
+use CPS::Future;
+
+our @EXPORT = qw(future await_future);
+
+sub future (&) {
+ my $f = $_[0]->(CPS::Future->new);
+ return $f if ((caller(1)||'') eq 'start');
+ await_future($f);
+}
+
+sub await_future {
+ my $f = shift;
+ return $f if $f->is_ready;
+ require Object::Remote;
+ my $loop = Object::Remote->current_loop;
+ $f->on_ready(sub { $loop->stop });
+ $loop->run;
+ return wantarray ? $f->get : ($f->get)[0];
+}
+
+package start;
+
+sub AUTOLOAD {
+ my $invocant = shift;
+ my ($method) = our $AUTOLOAD =~ /([^:]+)$/;
+ if (ref($invocant) eq 'ARRAY') {
+ return [ map $_->${\"start::${method}"}, @$invocant ];
+ }
+ my $res;
+ unless (eval { $res = $invocant->$method(@_); 1 }) {
+ my $f = CPS::Future->new;
+ $f->fail($@);
+ return $f;
+ }
+ unless (Scalar::Util::blessed($res) and $res->isa('CPS::Future')) {
+ my $f = CPS::Future->new;
+ $f->done($res);
+ return $f;
+ }
+ return $res;
+}
+
+package await;
+
+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;
+}
+
+1;
sub AUTOLOAD {
my $self = shift;
(my $method) = (our $AUTOLOAD =~ /([^:]+)$/);
+ if ((caller(0)||'') eq 'start') {
+ $method = "start::${method}";
+ }
$self->{remote}->${\$self->{method}}($method => @_);
}