ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-Fork-RPC/RPC/Async.pm
Revision: 1.16
Committed: Thu Sep 12 15:15:49 2019 UTC (7 years ago) by root
Branch: MAIN
Changes since 1.15: +11 -2 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 our $VERSION = 2; # protocol version
6
7 use Errno ();
8
9 use AnyEvent;
10
11 # declare only
12 sub AnyEvent::Fork::RPC::event;
13
14 sub do_exit { exit } # workaround for perl 5.14 and below
15
16 sub run {
17 my %kv = splice @_, pop;
18
19 my $rfh = shift;
20 my $wfh = fileno $rfh ? $rfh : *STDOUT;
21
22 my $function = delete $kv{function};
23 my $serialiser = delete $kv{serialiser};
24 my $rlen = delete $kv{rlen};
25 my $done = delete $kv{done};
26
27 $0 =~ s/^(\d+).*$/$1 $function/s;
28
29 {
30 package main;
31 my $init = delete $kv{init};
32 &$init if length $init;
33 $function = \&$function; # resolve function early for extra speed
34 }
35
36 my $busy = 1; # exit when == 0
37
38 my ($f, $t) = eval $serialiser; AE::log fatal => $@ if $@;
39 my ($wbuf, $ww);
40
41 my $wcb = sub {
42 my $len = syswrite $wfh, $wbuf;
43
44 unless (defined $len) {
45 if ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) {
46 undef $ww;
47 AE::log fatal => "AnyEvent::Fork::RPC: write error ($!), parent gone?";
48 }
49 }
50
51 substr $wbuf, 0, $len, "";
52
53 unless (length $wbuf) {
54 undef $ww;
55 unless ($busy) {
56 shutdown $wfh, 1;
57 @_ = (); goto &$done;
58 }
59 }
60 };
61
62 my $write = sub {
63 $wbuf .= $_[0];
64 $ww ||= AE::io $wfh, 1, $wcb;
65 };
66
67 *AnyEvent::Fork::RPC::event = sub {
68 $write->(pack "NN/a*", 0, &$f);
69 };
70
71 my ($rbuf, $rw);
72
73 my $len;
74
75 $rw = AE::io $rfh, 0, sub {
76 $rlen = $rlen * 2 + 16 if $rlen - 128 < length $rbuf;
77 $len = sysread $rfh, $rbuf, $rlen - length $rbuf, length $rbuf;
78
79 if ($len) {
80 while (8 <= length $rbuf) {
81 (my $id, $len) = unpack "NN", $rbuf;
82 8 + $len <= length $rbuf
83 or last;
84
85 my @r = $t->(substr $rbuf, 8, $len);
86 substr $rbuf, 0, 8 + $len, "";
87
88 ++$busy;
89 $function->(sub {
90 --$busy;
91 $write->(pack "NN/a*", $id, &$f);
92 }, @r);
93 }
94 } elsif (defined $len or $! == Errno::EINVAL) { # EINVAL is for microshit windoze
95 undef $rw;
96 --$busy;
97 $ww ||= AE::io $wfh, 1, $wcb;
98 } elsif ($! != Errno::EAGAIN && $! != Errno::EWOULDBLOCK) {
99 undef $rw;
100 AE::log fatal => "AnyEvent::Fork::RPC: read error in child: $!";
101 }
102 };
103
104 $AnyEvent::MODEL eq "AnyEvent::Impl::EV"
105 ? EV::run ()
106 : AE::cv->recv;
107 }
108
109 1
110