Вот возможное решение, использующее потоки и разделение потоков.Большая часть кода просто макетирует тест и эмулирует потоки, которые должны выполнить «работу» до завершения.В этом примере основной поток порождает семь потоков, каждый из которых имеет случайное количество времени, которое они должны выполнять «работу».Потоки не могут начать работать, пока другие потоки, от которых они зависят (установленные в массиве зависимостей), не закончили.Вы можете изменить зависимости потоков и запустить пример несколько раз, чтобы проиллюстрировать, что он работает правильно.
Кроме того, каждый поток можно завершить после его запуска, а основной поток - после завершения всех подпотоковпроверка статуса хэша.
use strict;
use warnings;
use threads;
use threads::shared;
my %status : shared;
my $dependencies = [
{3 => 1}, #three can only run after one has finished...
{4 => 1}, #four can only run after one has finished...
{5 => 2}, #five can only run after two has finished...
{6 => 1}, #etc...
{6 => 2},
{7 => 1},
{7 => 2}
];
main();
sub main{
foreach my $thread_number (1..7){
spawn_thread($thread_number);
}
while(1){
print "I am the main thread\n";
sleep(1);
}
}
sub spawn_thread{
my $thread_number = shift;
$status{$thread_number} = 'wait';
my $thr = threads->new(\&thread_routine, $thread_number);
}
sub thread_routine{
my $thread_number = shift;
my $working_time_left = int(rand(5)) + 1; #make a random time that this thread needs to "work"
while(1){
print "I am thread number $thread_number with status $status{$thread_number}\n";
{
lock(%status);
#see if this thread is active; if so, see if it finished running running
if ($status{$thread_number} eq 'active'){
if ($working_time_left <= 0){
$status{$thread_number} = 'ran';
}
}
else{
#see if we can activate
if ($status{$thread_number} eq 'wait'){
my $can_activate = 1;
foreach my $index (0..$#$dependencies){
if (exists $dependencies->[$index]->{$thread_number}){
if ($status{$dependencies->[$index]->{$thread_number}} ne 'ran'){
$can_activate = 0;
last;
}
}
}
if ($can_activate){
$status{$thread_number} = "active";
}
}
}
}
sleep(1);
if ($status{$thread_number} eq 'active'){ #do "work"
$working_time_left--;
}
}
}