ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-Fork-RPC/RPC/Async.pm
Revision: 1.4
Committed: Sat Apr 27 23:49:01 2013 UTC (13 years, 4 months ago) by root
Branch: MAIN
CVS Tags: rel-1_1
Changes since 1.3: +12 -10 lines
Log Message:
*** empty log message ***

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