use Proc::Simple;
$| = 1; # debuffer output
$max_parallel_jobs = 5; # jobs processed in parallel
@running = (); # array of running jobs
foreach $job (1..9) { # create pseudo jobs
push(@todo, "sleep 3");
}
######################################################################
# while there are jobs to do
while($#todo >= 0 || $#running >= 0) { # or started ones are running
@running = grep { $_->poll() } @running; # remove finished jobs
if($#running + 1 < $max_parallel_jobs && # space free in running?
defined($job = pop(@todo))) { # ... and job available
print "Starting job '$job' ... ";
$proc = Proc::Simple->new(); # new process
$proc->start($job) || die "Cannot start job $job";
push(@running, $proc); # include in running list
print "STARTED. (Remaining: ", $#todo+1,
" Running: ", $#running + 1, ")\n";
next; # proceed without delay
}
sleep(1); # pause ... and proceed
}
Cuando se ejecuta, produce esta salida:
$ perl eg/parproc.pl Starting job 'sleep 3' ... STARTED. (Remaining: 8 Running: 1) Starting job 'sleep 3' ... STARTED. (Remaining: 7 Running: 2) Starting job 'sleep 3' ... STARTED. (Remaining: 6 Running: 3) Starting job 'sleep 3' ... STARTED. (Remaining: 5 Running: 4) Starting job 'sleep 3' ... STARTED. (Remaining: 4 Running: 5) Starting job 'sleep 3' ... STARTED. (Remaining: 3 Running: 5) Starting job 'sleep 3' ... STARTED. (Remaining: 2 Running: 5) Starting job 'sleep 3' ... STARTED. (Remaining: 1 Running: 3) Starting job 'sleep 3' ... STARTED. (Remaining: 0 Running: 4)Basándose en Proc::Simple escriba un módulo
Proc::RPC que de funcionalidades
similares:
Posibles Consideraciones:
start para un objeto sobre el que hay un proceso ya arrancado?
use vars qw(%EXIT_STATUS %INTERVAL %DESTROYED) ¿Es posible reconvertir las variables globales de paquete a variables léxicas?
start y añadir un método join similar a wait
pero que para los procesos hijo
que ejecutan código Perl retorna una estructura de datos Perl. Usando la API de
Proc::Simple::Async
podría ser utilizada así:
$proc = async { map { $_ * $_ } @_ } , 1..3;
...
my @r = $proc->join(); # @r es ahora (1, 4, 9)
Puede usar Data::Dumper
o Storable
para serializar los datos retornados.
Para ello deberá modificar el método start de Proc::Simple:
sub start {
my $self = shift;
my ($func, @params) = @_;
# Reap Zombies automatically
$SIG{'CHLD'} = \&THE_REAPER;
# Fork a child process
$self->{'pid'} = fork();
return 0 unless defined $self->{'pid'}; # return Error if fork failed
if($self->{pid} == 0) { # Child
if (defined $self->{'redirect_stderr'}) { ... }
if (defined $self->{'redirect_stdout'}) { ... }
if(ref($func) eq "CODE") {
my @r = $func->(@params);
# Serialize @r in a temp file using Data::Dumper o Storable u otro ...
$self->serialize(@r);
exit 0; # Start perl subroutine
} else {
exec $func, @params; # Start shell process
exit 0; # In case something goes wrong
}
} elsif($self->{'pid'} > 0) { # Parent:
...
} else {
return 0; # this shouldn't occur
}
}
El método join funciona como el método wait pero lee y evalúa
los contenidos del fichero generado por el proceso hijo.
Es posible que necesite atributos adicionales para guardar el nombre del fichero
mediante el que se comunicarán padre e hijo.
Casiano Rodríguez León
