MCE
view release on metacpan or search on metacpan
lib/MCE/Child.pm view on Meta::CPAN
sub create {
my $caller = caller();
my $mngd = $_MNGD->{ "$$.$_tid.$caller" } || do {
# construct mngd internally on first use unless defined
init( caller => $caller ); $_MNGD->{ "$$.$_tid.$caller" };
};
shift if ( $_[0] eq __PACKAGE__ );
# ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~
my $self = bless ref $_[0] eq 'HASH' ? { %{ shift() } } : { }, __PACKAGE__;
$self->{IGNORE} = 1 if $SIG{CHLD} eq 'IGNORE';
$self->{MGR_ID} = $mngd->{MGR_ID}, $self->{PKG} = $mngd->{PKG};
$self->{ident } = shift if ( !ref $_[0] && ref $_[1] eq 'CODE' );
my $func = shift; $func = $caller.'::'.$func
if ( !ref $func && length $func && index($func,':') < 0 );
if ( !defined $func ) {
local $\; print {*STDERR} "code function is not specified or valid\n";
return undef;
}
my ( $list, $max_workers, $pkg ) = (
$_LIST->{ $mngd->{PKG} }, $mngd->{max_workers}, $mngd->{PKG}
);
$_DATA->{"$pkg:id"} = 10000 if ( ( my $id = ++$_DATA->{"$pkg:id"} ) >= 2e9 );
# Reap completed child processes.
{
local ($SIG{CHLD}, $!, $?, $_);
map {
$_ = substr($_, 1); # strip leading 'R'
my $child = $list->del($_);
if ( ! $child->{REAPED} ) {
waitpid($child->{WRK_ID}, 0);
_reap_child($child, 0);
}
();
}
$_DATA->{$pkg}->get_done();
}
# Wait for a slot if saturated.
_wait_one($pkg) if ( $max_workers && $list->len() >= $max_workers );
# ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~ ~~~
$MCE::_GMUTEX->lock() if ( $_tid && $MCE::_GMUTEX );
my @args = @_; @_ = (); # To avoid (Scalars leaked: N) messages
my ( $killed, $pid );
{
local $SIG{TERM} = local $SIG{INT} = sub { $killed = $_[0] }
if ( !$_is_MSWin32 && $] ge '5.010001' );
local $SIG{TTIN}, local $SIG{TTOU}, local $SIG{WINCH}
if ( !$_is_MSWin32 );
$pid = fork();
if ( !defined $pid ) { # error
local $\; print {*STDERR} "fork error: $!\n";
}
elsif ( $pid ) { # parent
$self->{WRK_ID} = $pid;
$list->set($pid, $self);
$mngd->{on_start}->($pid, $self->{ident}) if $mngd->{on_start};
}
else { # child
%{ $_LIST } = (), $_SELF = $self;
local $SIG{TERM} = local $SIG{INT} = local $SIG{ABRT} = \&_trap,
local $SIG{SEGV} = local $SIG{HUP} = \&_trap,
local $SIG{QUIT} = \&_quit;
local $SIG{CHLD};
MCE::Shared::init() if $INC{'MCE/Shared.pm'};
$_DATA->{ $_SELF->{PKG} }->set('S'.$$, '') unless $self->{IGNORE};
CORE::kill($killed, $$) if $killed;
MCE::Child->_clear() if $INC{'MCE/Child.pm'};
MCE::Hobo->_clear() if $INC{'MCE/Hobo.pm'};
# Set the seed of the base generator uniquely between workers.
# The new seed is computed using the current seed and ID value.
# One may set the seed at the application level for predictable
# results. Ditto for PDL, Math::Prime::Util, Math::Random, and
# Math::Random::MT::Auto.
{
my $seed = abs($_DATA->{"$pkg:seed"} - ($id * 100000)) % 2147483560;
CORE::srand($seed);
PDL::srand($seed) if $INC{'PDL.pm'} && PDL->can('srand'); # PDL 2.062 ~ 2.089
PDL::srandom($seed) if $INC{'PDL.pm'} && PDL->can('srandom'); # PDL 2.089_01+
Math::Prime::Util::srand($seed) if $INC{'Math/Prime/Util.pm'};
}
if ( $INC{'Math/Random.pm'} ) {
my $cur_seed = Math::Random::random_get_seed();
my $new_seed = ($cur_seed < 1073741781)
? $cur_seed + ((abs($id) * 10000) % 1073741780)
: $cur_seed - ((abs($id) * 10000) % 1073741780);
Math::Random::random_set_seed($new_seed, $new_seed);
}
if ( $INC{'Math/Random/MT/Auto.pm'} ) {
my $cur_seed = Math::Random::MT::Auto::get_seed()->[0];
my $new_seed = ($cur_seed < 1073741781)
? $cur_seed + ((abs($id) * 10000) % 1073741780)
: $cur_seed - ((abs($id) * 10000) % 1073741780);
Math::Random::MT::Auto::set_seed($new_seed);
( run in 5.815 seconds using v1.01-cache-2.11-cpan-b16cb0d3907 )