#!/usr/bin/env perl -w use strict; use Parallel::ForkManager; use 5.012; my $max_procs = 5; my @name_queue = qw( bot403 ); my @future_names = qw( Fred Jim Lily Steve Jessica Bob Dave Christine Rico Sara ); my $pm = new Parallel::ForkManager($max_procs); # Track children in progress my %working; # Setup a callback for when a child finishes up so we can # get it's exit code $pm->run_on_finish( sub { my ($pid, $exit_code, $ident) = @_; print "** $ident just got out of the pool ". "with PID $pid and exit code: $exit_code\n"; my $new = shift @future_names; # Done with this work unit. shift @name_queue; # Get future work to do (oversimplification of my real problem) push @name_queue, $new if $new; # Mark this entry as no longer in progress delete $working{$ident}; } ); $pm->run_on_start( sub { my ($pid,$ident)=@_; print "** $ident started, pid: $pid\n"; } ); $pm->run_on_wait( sub { print "** Have to wait for one children ...\n" }, 10 ); while( @name_queue || scalar keys %working ){ # Screen out entries in progress so we don't duplicate work. my @to_process = grep { ! $working{$_} } @name_queue; if( !@to_process ){ say "Waiting for children to finish to find new names"; sleep 10; next; } foreach my $child (@to_process){ $working{$child} = 1; $pm->start($child) and next; # This code is the child process say "This is $child"; sleep 3+rand(5); $pm->finish(0); # pass an exit code to finish } } print "Waiting for Children...\n"; $pm->wait_all_children; print "Everybody is out of the pool!\n";