1 | =head1 NAME |
1 | =head1 NAME |
2 | |
2 | |
3 | AnyEvent::Fork::RPC - simple RPC extension for AnyEvent::Fork |
3 | AnyEvent::Fork::RPC - simple RPC extension for AnyEvent::Fork |
4 | |
4 | |
5 | THE API IS NOT FINISHED, CONSIDER THIS A TECHNOLOGY DEMO |
|
|
6 | |
|
|
7 | =head1 SYNOPSIS |
5 | =head1 SYNOPSIS |
8 | |
6 | |
|
|
7 | use AnyEvent::Fork; |
9 | use AnyEvent::Fork::RPC; |
8 | use AnyEvent::Fork::RPC; |
10 | # use AnyEvent::Fork is not needed |
|
|
11 | |
9 | |
12 | my $rpc = AnyEvent::Fork |
10 | my $rpc = AnyEvent::Fork |
13 | ->new |
11 | ->new |
14 | ->require ("MyModule") |
12 | ->require ("MyModule") |
15 | ->AnyEvent::Fork::RPC::run ( |
13 | ->AnyEvent::Fork::RPC::run ( |
… | |
… | |
28 | $cv->recv; |
26 | $cv->recv; |
29 | |
27 | |
30 | =head1 DESCRIPTION |
28 | =head1 DESCRIPTION |
31 | |
29 | |
32 | This module implements a simple RPC protocol and backend for processes |
30 | This module implements a simple RPC protocol and backend for processes |
33 | created via L<AnyEvent::Fork>, allowing you to call a function in the |
31 | created via L<AnyEvent::Fork> (or L<AnyEvent::Fork::Remote>), allowing you |
34 | child process and receive its return values (up to 4GB serialised). |
32 | to call a function in the child process and receive its return values (up |
|
|
33 | to 4GB serialised). |
35 | |
34 | |
36 | It implements two different backends: a synchronous one that works like a |
35 | It implements two different backends: a synchronous one that works like a |
37 | normal function call, and an asynchronous one that can run multiple jobs |
36 | normal function call, and an asynchronous one that can run multiple jobs |
38 | concurrently in the child, using AnyEvent. |
37 | concurrently in the child, using AnyEvent. |
39 | |
38 | |
40 | It also implements an asynchronous event mechanism from the child to the |
39 | It also implements an asynchronous event mechanism from the child to the |
41 | parent, that could be used for progress indications or other information. |
40 | parent, that could be used for progress indications or other information. |
42 | |
|
|
43 | Loading this module also always loads L<AnyEvent::Fork>, so you can make a |
|
|
44 | separate C<use AnyEvent::Fork> if you wish, but you don't have to. |
|
|
45 | |
41 | |
46 | =head1 EXAMPLES |
42 | =head1 EXAMPLES |
47 | |
43 | |
48 | =head2 Example 1: Synchronous Backend |
44 | =head2 Example 1: Synchronous Backend |
49 | |
45 | |
… | |
… | |
53 | silly, but illustrates the use of events. |
49 | silly, but illustrates the use of events. |
54 | |
50 | |
55 | First the parent process: |
51 | First the parent process: |
56 | |
52 | |
57 | use AnyEvent; |
53 | use AnyEvent; |
|
|
54 | use AnyEvent::Fork; |
58 | use AnyEvent::Fork::RPC; |
55 | use AnyEvent::Fork::RPC; |
59 | |
56 | |
60 | my $done = AE::cv; |
57 | my $done = AE::cv; |
61 | |
58 | |
62 | my $rpc = AnyEvent::Fork |
59 | my $rpc = AnyEvent::Fork |
… | |
… | |
193 | so silly anymore. |
190 | so silly anymore. |
194 | |
191 | |
195 | Without further ado, here is the code: |
192 | Without further ado, here is the code: |
196 | |
193 | |
197 | use AnyEvent; |
194 | use AnyEvent; |
|
|
195 | use AnyEvent::Fork; |
198 | use AnyEvent::Fork::RPC; |
196 | use AnyEvent::Fork::RPC; |
199 | |
197 | |
200 | my $done = AE::cv; |
198 | my $done = AE::cv; |
201 | |
199 | |
202 | my $rpc = AnyEvent::Fork |
200 | my $rpc = AnyEvent::Fork |
… | |
… | |
305 | |
303 | |
306 | use Errno (); |
304 | use Errno (); |
307 | use Guard (); |
305 | use Guard (); |
308 | |
306 | |
309 | use AnyEvent; |
307 | use AnyEvent; |
310 | use AnyEvent::Fork; # we don't actually depend on it, this is for convenience |
|
|
311 | |
308 | |
312 | our $VERSION = 0.1; |
309 | our $VERSION = 1.1; |
313 | |
310 | |
314 | =item my $rpc = AnyEvent::Fork::RPC::run $fork, $function, [key => value...] |
311 | =item my $rpc = AnyEvent::Fork::RPC::run $fork, $function, [key => value...] |
315 | |
312 | |
316 | The traditional way to call it. But it is way cooler to call it in the |
313 | The traditional way to call it. But it is way cooler to call it in the |
317 | following way: |
314 | following way: |
… | |
… | |
524 | $rlen = $rlen * 2 + 16 if $rlen - 128 < length $rbuf; |
521 | $rlen = $rlen * 2 + 16 if $rlen - 128 < length $rbuf; |
525 | $len = sysread $fh, $rbuf, $rlen - length $rbuf, length $rbuf; |
522 | $len = sysread $fh, $rbuf, $rlen - length $rbuf, length $rbuf; |
526 | |
523 | |
527 | if ($len) { |
524 | if ($len) { |
528 | while (8 <= length $rbuf) { |
525 | while (8 <= length $rbuf) { |
529 | ($id, $len) = unpack "LL", $rbuf; |
526 | ($id, $len) = unpack "NN", $rbuf; |
530 | 8 + $len <= length $rbuf |
527 | 8 + $len <= length $rbuf |
531 | or last; |
528 | or last; |
532 | |
529 | |
533 | my @r = $t->(substr $rbuf, 8, $len); |
530 | my @r = $t->(substr $rbuf, 8, $len); |
534 | substr $rbuf, 0, 8 + $len, ""; |
531 | substr $rbuf, 0, 8 + $len, ""; |
… | |
… | |
579 | |
576 | |
580 | $rcb{$id} = pop; |
577 | $rcb{$id} = pop; |
581 | |
578 | |
582 | $guard if 0; # keep it alive |
579 | $guard if 0; # keep it alive |
583 | |
580 | |
584 | $wbuf .= pack "LL/a*", $id, &$f; |
581 | $wbuf .= pack "NN/a*", $id, &$f; |
585 | $ww ||= $fh && AE::io $fh, 1, $wcb; |
582 | $ww ||= $fh && AE::io $fh, 1, $wcb; |
586 | } |
583 | } |
587 | : sub { |
584 | : sub { |
588 | push @rcb, pop; |
585 | push @rcb, pop; |
589 | |
586 | |
590 | $guard; # keep it alive |
587 | $guard; # keep it alive |
591 | |
588 | |
592 | $wbuf .= pack "L/a*", &$f; |
589 | $wbuf .= pack "N/a*", &$f; |
593 | $ww ||= $fh && AE::io $fh, 1, $wcb; |
590 | $ww ||= $fh && AE::io $fh, 1, $wcb; |
594 | } |
591 | } |
595 | } |
592 | } |
596 | |
593 | |
597 | =item $rpc->(..., $cb->(...)) |
594 | =item $rpc->(..., $cb->(...)) |
… | |
… | |
728 | half it has passed earlier. |
725 | half it has passed earlier. |
729 | |
726 | |
730 | Here is some (untested) pseudocode to that effect: |
727 | Here is some (untested) pseudocode to that effect: |
731 | |
728 | |
732 | use AnyEvent::Util; |
729 | use AnyEvent::Util; |
|
|
730 | use AnyEvent::Fork; |
733 | use AnyEvent::Fork::RPC; |
731 | use AnyEvent::Fork::RPC; |
734 | use IO::FDPass; |
732 | use IO::FDPass; |
735 | |
733 | |
736 | my ($s1, $s2) = AnyEvent::Util::portable_socketpair; |
734 | my ($s1, $s2) = AnyEvent::Util::portable_socketpair; |
737 | |
735 | |
… | |
… | |
773 | |
771 | |
774 | Of course, this might be blocking if you pass a lot of file descriptors, |
772 | Of course, this might be blocking if you pass a lot of file descriptors, |
775 | so you might want to look into L<AnyEvent::FDpasser> which can handle the |
773 | so you might want to look into L<AnyEvent::FDpasser> which can handle the |
776 | gory details. |
774 | gory details. |
777 | |
775 | |
|
|
776 | =head1 EXCEPTIONS |
|
|
777 | |
|
|
778 | There are no provisions whatsoever for catching exceptions at this time - |
|
|
779 | in the child, exeptions might kill the process, causing calls to be lost |
|
|
780 | and the parent encountering a fatal error. In the parent, exceptions in |
|
|
781 | the result callback will not be caught and cause undefined behaviour. |
|
|
782 | |
778 | =head1 SEE ALSO |
783 | =head1 SEE ALSO |
779 | |
784 | |
780 | L<AnyEvent::Fork>, to create the processes in the first place. |
785 | L<AnyEvent::Fork>, to create the processes in the first place. |
|
|
786 | |
|
|
787 | L<AnyEvent::Fork::Remote>, likewise, but helpful for remote processes. |
781 | |
788 | |
782 | L<AnyEvent::Fork::Pool>, to manage whole pools of processes. |
789 | L<AnyEvent::Fork::Pool>, to manage whole pools of processes. |
783 | |
790 | |
784 | =head1 AUTHOR AND CONTACT INFORMATION |
791 | =head1 AUTHOR AND CONTACT INFORMATION |
785 | |
792 | |