pyr0
pyr0

Reputation: 377

parallel forking without Parallel::ForkManager?

is there a way to simply fork into i.g. 4 threads and check the states of the childs during a while loop? I read something about SIGCHLD (http://perldoc.perl.org/perlipc.html) but I'm not familiar with this stuff and don't know how to use this. Btw. there is no reason not to use Parallel::ForkManager, I am just interested... and tried something like this

use strict;
use warnings;
use POSIX qw/ WNOHANG /;
my @a = qw( 1 2 3 4 5 6 7 8 9 0 );
my @childs;
$#childs=4;

foreach my $a (@a){
    my $add=0;
    while(!$add){
        $add=0;
        foreach(0..$#childs){
            next if defined $childs[$_] && $childs[$_]!=0;
            $add=1;
            my $pid=fork();
            if ($pid == 0){
                &process($a);       
                exit;
            } else {    
                $childs[$_]=$pid;
                waitpid($pid,WNOHANG);              
            }           
        }
    }
}

sub process(){
    my $x = shift;  
    sleep(int(rand(10)));
    print $x."\n";
}

Upvotes: 1

Views: 313

Answers (1)

ikegami
ikegami

Reputation: 386706

Your code doesn't look anything like the code you'd be using if you used F::PM, so that should have raised a red flag!

use strict;
use warnings;

use POSIX qw( _exit );

sub process {
   my ($job) = @_;
   sleep(1+int(rand(4)));
   print("$job\n");
}

my $max_children = 4;
my %children;

for my $job (0..9) {
   # Wait for the number of children to be less than the max.
   while (keys(%children) >= $max_children) {
      my $pid = wait();
      delete $children{$pid};
   }

   # Start a new child.
   if (my $pid = fork()) {
      # In parent
      ++$children{$pid};
   } else {
      # In child
      process($job);
      _exit(0);
   }
}

# Wait for remaining children to finish.
while (keys(%children)) {
   my $pid = wait();
   delete $children{$pid};
}

This is basically a simplified version of P::FM and user code combined.

Upvotes: 1

Related Questions