ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-Fork-RPC/RPC/Async.pm
Revision: 1.9
Committed: Tue Oct 15 09:15:59 2013 UTC (12 years, 11 months ago) by root
Branch: MAIN
CVS Tags: rel-1_21
Changes since 1.8: +2 -0 lines
Log Message:
1.21

File Contents

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