From: Matt S Trout Date: Thu, 17 May 2012 23:15:36 +0000 (+0000) Subject: parti8al conversion to future based system; start still being weird X-Git-Tag: v0.001001~57 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=dc28afe80b27f0eb81eef66e6ba554a7c1fb6e41;p=scpubgit%2FObject-Remote.git parti8al conversion to future based system; start still being weird --- diff --git a/bin/object-remote-node b/bin/object-remote-node index 807f834..acdf165 100755 --- a/bin/object-remote-node +++ b/bin/object-remote-node @@ -3,6 +3,7 @@ use strictures 1; use Object::Remote::Connector::STDIO; use Object::Remote; +use CPS::Future; #$Object::Remote::Connection::DEBUG = 1; @@ -10,7 +11,11 @@ my $c = Object::Remote::Connector::STDIO->new->connect; 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"; diff --git a/lib/Object/Remote.pm b/lib/Object/Remote.pm index 64355af..25f0349 100644 --- a/lib/Object/Remote.pm +++ b/lib/Object/Remote.pm @@ -3,6 +3,7 @@ package Object::Remote; 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; @@ -40,7 +41,7 @@ sub BUILD { 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}||[]} @@ -57,9 +58,10 @@ sub current_loop { 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 { @@ -73,14 +75,6 @@ sub call_discard_free { $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; diff --git a/lib/Object/Remote/Connection.pm b/lib/Object/Remote/Connection.pm index 4e3348a..3b66cd5 100644 --- a/lib/Object/Remote/Connection.pm +++ b/lib/Object/Remote/Connection.pm @@ -1,6 +1,6 @@ package Object::Remote::Connection; -use CPS::Future; +use Object::Remote::Future; use Object::Remote::Null; use Object::Remote; use IO::Handle; @@ -156,7 +156,7 @@ sub _receive_data_from { $self->_receive($1); } } else { - $self->on_close->(); + $self->on_close->done(); } } @@ -201,6 +201,12 @@ sub receive_class_call { 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( diff --git a/lib/Object/Remote/Future.pm b/lib/Object/Remote/Future.pm new file mode 100644 index 0000000..2fe171b --- /dev/null +++ b/lib/Object/Remote/Future.pm @@ -0,0 +1,60 @@ +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; diff --git a/lib/Object/Remote/Proxy.pm b/lib/Object/Remote/Proxy.pm index 8541056..af6a902 100644 --- a/lib/Object/Remote/Proxy.pm +++ b/lib/Object/Remote/Proxy.pm @@ -5,6 +5,9 @@ use strictures 1; sub AUTOLOAD { my $self = shift; (my $method) = (our $AUTOLOAD =~ /([^:]+)$/); + if ((caller(0)||'') eq 'start') { + $method = "start::${method}"; + } $self->{remote}->${\$self->{method}}($method => @_); }