I came across a wonderful site, by Jason Brownlee, demonstrating Barriers using Python. That's what I want for MCE::Barrier to accomplish. Hold on... I'm not finished yet. The MCE::Barrier, MCE::Semaphore, and MCE::Simple modules will be released once completing the documentation and test scripts.
The barrier wait method supports two modes; list-context or exception-raised (if aborted or timed out). Notice also, the spawn keyword being used in a loop. That works too :)
Barrier with a Timeout
# Perl replica of using a Barrier with a Timeout
# https://superfastpython.com/multiprocessing-barrier-in-python/
use MCE::Simple -strict, -signatures;
use MCE::Barrier;
use Time::HiRes 'sleep';
use Try::Tiny;
STDOUT->autoflush(1);
sub task ($barrier, $number) {
# generate a unique value and block for a moment
my $value = rand() * 10; sleep($value);
# report result
say "Process ${number} done, got: ${value}";
# wait on all other processes to complete
# my ($remaining, $error) = $barrier->wait;
# or via exception handling
try {
$barrier->wait;
}
catch {
# pass
};
}
sub main () {
# create a barrier plus one for the main process
my $barrier = MCE::Barrier->new(5 + 1);
# create the worker processes
spawn task($barrier, $_) for 1..5;
# wait for all processes to finish
# my ($remaining, $error) = $barrier->wait;
# or via exception handling
try {
$barrier->wait(timeout => 5);
say "All processes have their result";
}
catch {
# $_ = "Operation timed out ..."
say "Some processes did not finish on time...";
};
# reap the worker processes
sync;
}
main();
__END__
Process 2 done, got: 2.20488202831806
Process 1 done, got: 4.51354761681618
Some processes did not finish on time...
Process 5 done, got: 5.27888526282371
Process 4 done, got: 7.58755085132183
Process 3 done, got: 9.89621643981994
Barrier with an Action
# Perl replica of using a Barrier with an Action
# https://superfastpython.com/multiprocessing-barrier-in-python/
use MCE::Simple -strict, -signatures;
use MCE::Barrier;
use Time::HiRes 'sleep';
STDOUT->autoflush(1);
sub report () {
# report once all processes are done
say "All processes have their result";
}
sub task ($barrier, $number) {
# generate a unique value and block for a moment
my $value = rand() * 10; sleep($value);
# report result
say "Process ${number} done, got: ${value}";
# wait on all other processes to complete
my ($remaining, $error) = $barrier->wait;
# an alternative to using the "action" argument
if ($remaining == 0) {
say "I, process ${number}, was last...";
}
}
sub main () {
# create a barrier, not including the main process
my $barrier = MCE::Barrier->new(5, before_release => \&report);
# create the worker processes
spawn task($barrier, $_) for 1..5;
# reap the worker processes
sync;
}
main();
__END__
Process 1 done, got: 1.25912054515542
Process 5 done, got: 2.02445819116296
Process 4 done, got: 4.33312377966107
Process 3 done, got: 6.64178936815919
Process 2 done, got: 8.9504549566573
All processes have their result
I, process 2, was last...
Aborting a Barrier
# Perl replica of Aborting a Barrier
# https://superfastpython.com/multiprocessing-barrier-in-python/
use MCE::Simple -strict, -signatures;
use MCE::Barrier;
use Time::HiRes 'sleep';
use Try::Tiny;
STDOUT->autoflush(1);
sub task ($barrier, $number) {
# generate a unique value and block for a moment
my $value = rand() * 10; sleep($value);
# report result
say "Process ${number} done, got: ${value}";
# check if the result was "bad"
if ($value > 8) {
say "Process ${number} aborting...";
$barrier->abort;
}
else {
# wait on all other processes to complete
# my ($remaining, $error) = $barrier->wait;
# or via exception handling
try {
$barrier->wait;
}
catch {
# pass
};
}
}
sub main () {
# create a barrier plus one for the main process
my $barrier = MCE::Barrier->new(5 + 1);
# create the worker processes
spawn task($barrier, $_) for 1..5;
# wait for all processes to finish
# my ($remaining, $error) = $barrier->wait;
# or via exception handling
try {
$barrier->wait();
say "All processes have their result";
}
catch {
# $_ = "Barrier aborted ..."
say "At least one process aborted due to bad results";
};
# reap the worker processes
sync;
}
main();
__END__
Process 1 done, got: 1.12563261603103
Process 5 done, got: 1.89097026203857
Process 4 done, got: 4.19963585053669
Process 3 done, got: 6.5083014390348
Process 2 done, got: 8.81696702753292
Process 2 aborting...
At least one process aborted due to bad results