our $PID_IDLE;
our $WNOHANG;
sub _child_wait {
while (0 < (my $pid = waitpid -1, $WNOHANG)) {
$_->($pid, $?) for (values %{ $PID_CB{$pid} || {} }),
(values %{ $PID_CB{0} || {} });
}
undef $PID_IDLE;
}
sub _sigchld {
# make sure we deliver these changes "synchronous" with the event loop.
$CHLD_DELAY_W ||= AnyEvent->timer (after => 0, cb => sub {
undef $CHLD_DELAY_W;
&_child_wait;
});
}
sub child {
my (undef, %arg) = @_;
defined (my $pid = $arg{pid} + 0)
or Carp::croak "required option 'pid' is missing";
$PID_CB{$pid}{$arg{cb}} = $arg{cb};
unless ($WNOHANG) {
$WNOHANG = eval { local $SIG{__DIE__}; require POSIX; &POSIX::WNOHANG } || 1;
}
unless ($CHLD_W) {
$CHLD_W = AnyEvent->signal (signal => 'CHLD', cb => \&_sigchld);
# child could be a zombie already, so make at least one round
&_sigchld;
}
bless [$pid, $arg{cb}], "AnyEvent::Base::Child"
}
sub AnyEvent::Base::Child::DESTROY {
my ($pid, $cb) = @{$_[0]};
delete $PID_CB{$pid}{$cb};
delete $PID_CB{$pid} unless keys %{ $PID_CB{$pid} };
undef $CHLD_W unless keys %PID_CB;
}
package AnyEvent::CondVar;
our @ISA = AnyEvent::CondVar::Base::;
package AnyEvent::CondVar::Base;
use overload
'&{}' => sub { my $self = shift; sub { $self->send (@_) } },
fallback => 1;
sub _send {
# nop
}
sub send {
my $cv = shift;
$cv->{_ae_sent} = [@_];
(delete $cv->{_ae_cb})->($cv) if $cv->{_ae_cb};
$cv->_send;
}
sub croak {
$_[0]{_ae_croak} = $_[1];
$_[0]->send;
}
sub ready {
$_[0]{_ae_sent}
}
sub _wait {
AnyEvent->one_event while !$_[0]{_ae_sent};
}
sub recv {
$_[0]->_wait;
Carp::croak $_[0]{_ae_croak} if $_[0]{_ae_croak};
wantarray ? @{ $_[0]{_ae_sent} } : $_[0]{_ae_sent}[0]
}
sub cb {
$_[0]{_ae_cb} = $_[1] if @_ > 1;
$_[0]{_ae_cb}
}
sub begin {
++$_[0]{_ae_counter};
$_[0]{_ae_end_cb} = $_[1] if @_ > 1;
}
=11= |