AnyEvent-Fork-RPC
view release on metacpan or search on metacpan
my ($id, $len);
$rw = AE::io $fh, 0, sub {
$rlen = $rlen * 2 + 16 if $rlen - 128 < length $rbuf;
$len = sysread $fh, $rbuf, $rlen - length $rbuf, length $rbuf;
if ($len) {
while (8 <= length $rbuf) {
($id, $len) = unpack "NN", $rbuf;
8 + $len <= length $rbuf
or last;
my @r = $t->(substr $rbuf, 8, $len);
substr $rbuf, 0, 8 + $len, "";
if ($id) {
if (@rcb) {
(shift @rcb)->(@r);
} elsif (my $cb = delete $rcb{$id}) {
$cb->(@r);
} else {
undef $rw; undef $ww;
$on_error->("unexpected data from child");
}
} else {
$on_event->(@r);
}
}
} elsif (defined $len) {
undef $rw; undef $ww; # it ends here
if (@rcb || %rcb) {
$on_error->("unexpected eof");
} else {
$on_destroy->()
if $on_destroy;
}
} elsif ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) {
undef $rw; undef $ww; # it ends here
$on_error->("read: $!");
}
};
$ww ||= AE::io $fh, 1, $wcb;
});
my $guard = Guard::guard {
$shutdown = 1;
shutdown $fh, 1 if $fh && !$ww;
};
my $id;
$arg{async}
? sub {
$id = ($id == 0xffffffff ? 0 : $id) + 1;
$id = ($id == 0xffffffff ? 0 : $id) + 1 while exists $rcb{$id}; # rarely loops
$rcb{$id} = pop;
$guard if 0; # keep it alive
$wbuf .= pack "NN/a*", $id, &$f;
$ww ||= $fh && AE::io $fh, 1, $wcb;
}
: sub {
push @rcb, pop;
$guard; # keep it alive
$wbuf .= pack "N/a*", &$f;
$ww ||= $fh && AE::io $fh, 1, $wcb;
}
}
=item $rpc->(..., $cb->(...))
The RPC object returned by C<AnyEvent::Fork::RPC::run> is actually a code
reference. There are two things you can do with it: call it, and let it go
out of scope (let it get destroyed).
If C<async> was false when C<$rpc> was created (the default), then, if you
call C<$rpc>, the C<$function> is invoked with all arguments passed to
C<$rpc> except the last one (the callback). When the function returns, the
callback will be invoked with all the return values.
If C<async> was true, then the C<$function> receives an additional
initial argument, the result callback. In this case, returning from
C<$function> does nothing - the function only counts as "done" when the
result callback is called, and any arguments passed to it are considered
the return values. This makes it possible to "return" from event handlers
or e.g. Coro threads.
The other thing that can be done with the RPC object is to destroy it. In
this case, the child process will execute all remaining RPC calls, report
their results, and then exit.
See the examples section earlier in this document for some actual
examples.
=back
=head1 CHILD PROCESS USAGE
The following function is not available in this module. They are only
available in the namespace of this module when the child is running,
without having to load any extra modules. They are part of the child-side
API of L<AnyEvent::Fork::RPC>.
Note that these functions are typically not yet declared when code is
compiled into the child, because the backend module is only loaded when
you call C<run>, which is typically the last method you call on the fork
object.
Therefore, you either have to explicitly pre-load the right backend module
or mark calls to these functions as function calls, e.g.:
AnyEvent::Fork::RPC::event (0 => "five");
AnyEvent::Fork::RPC::event->(0 => "five");
&AnyEvent::Fork::RPC::flush;
=over 4
=item AnyEvent::Fork::RPC::event (...)
Send an event to the parent. Events are a bit like RPC calls made by the
child process to the parent, except that there is no notion of return
values.
( run in 1.095 second using v1.01-cache-2.11-cpan-df04353d9ac )