ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-Fork-RPC/RPC/Async.pm
Revision: 1.8
Committed: Sat Aug 31 19:51:25 2013 UTC (13 years ago) by root
Branch: MAIN
CVS Tags: rel-1_2
Changes since 1.7: +3 -3 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 package AnyEvent::Fork::RPC::Async;
2
3 use common::sense; # actually required to avoid spurious warnings...
4
5 use Errno ();
6
7 use AnyEvent;
8
9 # declare only
10 sub AnyEvent::Fork::RPC::event;
11
12 sub run {
13 my ($function, $init, $serialiser, $done) = splice @_, -4, 4;
14 my $rfh = shift;
15 my $wfh = fileno $rfh ? $rfh : *STDOUT;
16
17 $0 =~ s/^AnyEvent::Fork::RPC::Async::run of /$function of /;
18
19 {
20 package main;
21 &$init if length $init;
22 $function = \&$function; # resolve function early for extra speed
23 }
24
25 my $busy = 1; # exit when == 0
26
27 my ($f, $t) = eval $serialiser; AE::log fatal => $@ if $@;
28 my ($wbuf, $ww);
29
30 my $wcb = sub {
31 my $len = syswrite $wfh, $wbuf;
32
33 unless (defined $len) {
34 if ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) {
35 undef $ww;
36 AE::log fatal => "AnyEvent::Fork::RPC: write error ($!), parent gone?";
37 }
38 }
39
40 substr $wbuf, 0, $len, "";
41
42 unless (length $wbuf) {
43 undef $ww;
44 unless ($busy) {
45 shutdown $wfh, 1;
46 @_ = (); goto &$done;
47 }
48 }
49 };
50
51 my $write = sub {
52 $wbuf .= $_[0];
53 $ww ||= AE::io $wfh, 1, $wcb;
54 };
55
56 *AnyEvent::Fork::RPC::event = sub {
57 $write->(pack "NN/a*", 0, &$f);
58 };
59
60 my ($rlen, $rbuf, $rw) = 512 - 16;
61
62 my $len;
63
64 $rw = AE::io $rfh, 0, sub {
65 $rlen = $rlen * 2 + 16 if $rlen - 128 < length $rbuf;
66 $len = sysread $rfh, $rbuf, $rlen - length $rbuf, length $rbuf;
67
68 if ($len) {
69 while (8 <= length $rbuf) {
70 (my $id, $len) = unpack "NN", $rbuf;
71 8 + $len <= length $rbuf
72 or last;
73
74 my @r = $t->(substr $rbuf, 8, $len);
75 substr $rbuf, 0, 8 + $len, "";
76
77 ++$busy;
78 $function->(sub {
79 --$busy;
80 $write->(pack "NN/a*", $id, &$f);
81 }, @r);
82 }
83 } elsif (defined $len or $! == Errno::EINVAL) { # EINVAL is for microshit windoze
84 undef $rw;
85 --$busy;
86 $ww ||= AE::io $wfh, 1, $wcb;
87 } elsif ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) {
88 undef $rw;
89 AE::log fatal => "AnyEvent::Fork::RPC: read error in child: $!";
90 }
91 };
92
93 $AnyEvent::MODEL eq "EV"
94 ? EV::loop ()
95 : AE::cv->recv;
96 }
97
98 1
99