package My::Parallel::ForkManager; use POSIX ":sys_wait_h"; use strict; use vars qw($VERSION); $VERSION='0.7.5'; sub new { my ($c,$processes)=@_; my $h={ max_proc => $processes, processes => {}, in_child => 0, }; return bless($h,ref($c)||$c); }; sub start { my ($s,$identification)=@_; die "Cannot start another process while you are in the child process +" if $s->{in_child}; while ($s->{max_proc} && ( keys %{ $s->{processes} } ) >= $s->{max_p +roc}) { $s->on_wait; $s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef +); }; $s->wait_children; if ($s->{max_proc}) { my $pid=fork(); die "Cannot fork: $!" if !defined $pid; if ($pid) { $s->{processes}->{$pid}=$identification; $s->on_start($pid,$identification); } else { $s->{in_child}=1 if !$pid; } return $pid; } else { $s->{processes}->{$$}=$identification; $s->on_start($$,$identification); return 0; # Simulating the child which returns 0 } } sub finish { my ($s, $x)=@_; if ( $s->{in_child} ) { exit ($x || 0); } if ($s->{max_proc} == 0) { # max_proc == 0 $s->on_finish($$, $x ,$s->{processes}->{$$}, 0, 0); delete $s->{processes}->{$$}; } return 0; } sub wait_children { my ($s)=@_; return if !keys %{$s->{processes}}; my $kid; do { $kid = $s->wait_one_child(&WNOHANG); } while $kid > 0 || $kid < -1; # AS 5.6/Win32 returns negative PIDs }; *wait_childs=*wait_children; # compatibility sub wait_one_child { my ($s,$par)=@_; my $kid; while (1) { $kid = $s->_waitpid(-1,$par||=0); last if $kid == 0 || $kid == -1; # AS 5.6/Win32 returns negative P +IDs redo if !exists $s->{processes}->{$kid}; my $id = delete $s->{processes}->{$kid}; $s->on_finish( $kid, $? >> 8 , $id, $? & 0x7f, $? & 0x80 ? 1 : 0); last; } $kid; }; sub wait_all_children { my ($s)=@_; while (keys %{ $s->{processes} }) { $s->on_wait; $s->wait_one_child(defined $s->{on_wait_period} ? &WNOHANG : undef +); }; } *wait_all_childs=*wait_all_children; # compatibility; sub run_on_finish { my ($s,$code,$pid)=@_; $s->{on_finish}->{$pid || 0}=$code; } sub on_finish { my ($s,$pid,@par)=@_; my $code=$s->{on_finish}->{$pid} || $s->{on_finish}->{0} or return 0 +; $code->($pid,@par); }; sub run_on_wait { my ($s,$code, $period)=@_; $s->{on_wait}=$code; $s->{on_wait_period} = $period; } sub on_wait { my ($s)=@_; if(ref($s->{on_wait}) eq 'CODE') { $s->{on_wait}->(); if (defined $s->{on_wait_period}) { local $SIG{CHLD} = sub { } if ! defined $SIG{CHLD}; select undef, undef, undef, $s->{on_wait_period} }; }; }; sub run_on_start { my ($s,$code)=@_; $s->{on_start}=$code; } sub on_start { my ($s,@par)=@_; $s->{on_start}->(@par) if ref($s->{on_start}) eq 'CODE'; }; sub set_max_procs { my ($s, $mp)=@_; $s->{max_proc} = $mp; } # OS dependant code follows... sub _waitpid { # Call waitpid() in the standard Unix fashion. return waitpid($_[1],$_[2]); } # On ActiveState Perl 5.6/Win32 build 625, waitpid(-1, &WNOHANG) alway +s # blocks unless an actual PID other than -1 is given. sub _NT_waitpid { my ($s, $pid, $par) = @_; if ($par == &WNOHANG) { # Need to nonblock on each of our PIDs in th +e pool. my @pids = keys %{ $s->{processes} }; # Simulate -1 (no processes awaiting cleanup.) return -1 unless scalar(@pids); # Check each PID in the pool. my $kid; foreach $pid (@pids) { $kid = waitpid($pid, $par); return $kid if $kid != 0; # AS 5.6/Win32 returns negative PIDs. } return $kid; } else { # Normal waitpid() call. return waitpid($pid, $par); } } { local $^W = 0; if ($^O eq 'NT' or $^O eq 'MSWin32') { *_waitpid = \&_NT_waitpid; } } 1;
Note: a restrictive development environment is one that encourages the development of costly and buggy software. You have a perfectly good solution that was developed under the same development model that Perl itself was developed under. Is that seriously a big issue?
Being right, does not endow the right to be rude; politeness costs nothing.
Being unknowing, is not the same as being stupid.
Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
In reply to Re^3: Iteration through large array using a N number of forks.
by dragonchild
in thread Iteration through large array using a N number of forks.
by Spesh00
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |