Home > Net >  Perl - multithreading / fork / synchronize problem:
Perl - multithreading / fork / synchronize problem:

Time:09-17

I'm trying to work as an example for the following code:

    my $milon;
    my $pid = fork();
    die if not defined $pid;    
    if (not $pid) 
    {
        $milon->{$pid} = $pid;
        exit;
    }
    
    $milon->{3} = 4;        
    my $finished = wait();  
    print( "debug10: TEST = ", Dumper($milon));

output:

debug10: TEST = $VAR1 = {
          '3' => 4
        };

How do I make the dictionary keep both 3 => 4 and also the $pid => $pid? It doesn't have to be forking, it could be multithreading or NonBlocking IO, whichever is better according to what you think.

This is an example of course, I just want to conclude from this example to my real code.

CodePudding user response:

You need some memory that is shared between your threads/processes. The easiest is probably to use interpreter-based threads and threads::shared. For instance:

use threads;
use threads::shared;

my %milon :shared;

for (1 .. 2) {
    threads->create(sub {
        my $tid = threads->tid();
        $milon{$tid} = $tid;
    });
}

$milon{3} = 4;

$_->join for threads->list; # Wait for all threads to be done

print Dumper \%milon;

This outputs:

$VAR1 = {
          '1' => 1,
          '2' => 2,
          '3' => 4
        };

CodePudding user response:

Following sample code demonstrates usage of fork() to compute square of a number from an array @numbers (total 100) in parallel execution.

REAPER function assigned to $SIG{CHLD} signal cleans up completed child processes to avoid zombie processes hanging around in process table.

Investigate if fork() approach will fit your problem/task.

use strict;
use warnings;

use POSIX qw(strftime :sys_wait_h);
use Time::HiRes qw(usleep);

my $limit   = 10;
my $threads = $limit;
my @numbers = map { int(rand(100)) } 1..100;

sub REAPER {
    local $!;

    while( (my $pid = waitpid(-1, WNOHANG) ) > 0 && WIFEXITED($?) ) {
        $threads  ;
    }

    $SIG{CHLD} = \&REAPER;
}

$SIG{CHLD} = \&REAPER;

for ( @numbers ) {
    while( $threads == 0 or $threads > $limit ) { usleep(1) }

    my $pid = fork();

    die $! unless defined $pid;

    if( $pid ) {
        # parent
        $threads--;
    } else {
        # child
        my $n = compute_square($_);
        printf "Process m: = => %d\n", $$, $_, $n;
        exit 0;
    }
}

sub compute_square {
    my $num = shift;

    return $num*$num;
}
  • Related