IPC-MPS
view release on metacpan or search on metacpan
%vpid2pid = ();
$ipc_loop = 0;
@rcv = ();
%r_bufs = ();
%w_bufs = ();
%pack = ();
%unpack = ();
%closed = ();
$need_reset = 0;
$self_parent_fh = $parent;
$self_parent_vpid = $self_vpid;
$self_vpid = $vpid;
$fh2vpid{$self_parent_fh} = $self_parent_vpid;
$vpid2fh{$self_parent_vpid} = $self_parent_fh;
$fh2fh{$self_parent_fh} = $self_parent_fh;
$sel->add($self_parent_fh);
$spawn->();
exit;
}
else {
$vpid2pid{$vpid} = $kid_pid;
}
}
foreach (@spawn) {
my ($vpid, $child, $parent, $spawn) = @$_;
close $parent;
$fh2vpid{$child} = $vpid;
$vpid2fh{$vpid} = $child;
$fh2fh{$child} = $child;
$sel->add($child);
}
@spawn = ();
$receive->();
unless ($ipc_loop) {
$ipc_loop = 1;
ipc_loop();
$ipc_loop = 0;
}
}
sub wt($$) {
my ($waited_vpid, $waited_msg) = @_;
defined $waited_vpid or carp("Argument vpid required"), return;
defined $waited_msg or carp("Argument msg required"), return;
$waited_vpid = $self_parent_vpid if $waited_vpid == 0;
foreach my $i (0 .. $#rcv) {
my ($from, $msg, $args)= @{$rcv[$i]};
if ($from eq $waited_vpid and $msg eq $waited_msg) {
splice @rcv, $i, 1;
return wantarray ? @$args : $$args[0];
}
}
$DEBUG and print "Start waiting for '$waited_vpid -> $waited_msg' in $self_vpid (\$\$=$$)\n";
return ipc_loop($waited_vpid, $waited_msg);
}
sub ipc_loop(;$$) {
my ($waited_vpid, $waited_msg) = @_;
$DEBUG and print "Start ipc_loop in $self_vpid (\$\$=$$)\n";
RESET: while ($sel->count() and not $quit) {
foreach my $to (keys %snd) {
if (@{$snd{$to}}) {
my $fh = $vpid2fh{$to};
unless ($fh) {
if (@spawn) {
carp "Probably have forgotten to call receive.";
next;
} else {
if ($self_parent_fh) {
unless ($self_parent_closed) {
$fh = $self_parent_fh;
} else {
next;
}
} else {
carp "The addressee $to is unknown or has left in $self_vpid (\$\$=$$)\n";
next;
}
}
}
unless (exists $w_bufs{$fh}) {
my $packet;
if (my $pack = $pack{$fh}) {
$packet = $pack->(shift @{$snd{$to}});
} else {
$packet = freeze shift @{$snd{$to}};
}
my $buf = join "", pack("N", length $packet), $packet;
$w_bufs{$fh} = $buf;
$DEBUG and (@{$snd{$to}} or delete $snd{$to});
}
}
}
my $w_sel = IO::Select->new(map { $fh2fh{$_} } keys %w_bufs);
if ($DEBUG > 1) {
print "Select count from $self_vpid, sel->count=", $sel->count(), ", w_sel->count=", $w_sel->count(), "\n",
$DEBUG > 2 ? Data::Dumper::Dumper({ snd => \%snd, r_bufs => \%r_bufs, w_bufs => \%w_bufs }) : "";
( run in 1.100 second using v1.01-cache-2.11-cpan-ad19def0cd9 )