dr.jekyllandme has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I need to write a script that kicks off several processes at once. But between each fork, there should be delay of n seconds. I am using Parallel:ForkManager and know that I have to use sleep but not sure on the how.
#!/usr/software/bin/perl5.8.8 -w use strict; use warnings; use Cwd qw(abs_path); use Parallel::ForkManager; my $pm = new Parallel::ForkManager(8); $pm->run_on_finish(sub { my($pid, $exit_code) = @_; my $output = "$pid has finished with exit code $exit_code.\n"; print $output; }); foreach my $x (0..2) { $pm->start($x) and next; sleep(1); # I want to sleep for 2 mins before the next process kic +ks off. my $time = time; print "$x\n"; print "$time\n"; $pm->finish(); } $pm->wait_all_children;
The above code is wrong because every process sleeps for 2 mins and they resume at the same time. Instead I would like process 0 to start, 2 mins goes by, then process 1 joins, 2 mins go by and then process 3 joins, etc... Is there someway to do this? Thanks for your help.

Replies are listed 'Best First'.
Re: How to sleep before the next fork kicks off?
by GrandFather (Saint) on Jan 17, 2014 at 02:21 UTC

    As written your delay is in the child fork. Instead you need to delay in the parent fork:

    #!/usr/software/bin/perl5.8.8 -w use strict; use warnings; use Cwd qw(abs_path); use Parallel::ForkManager; my $pm = new Parallel::ForkManager(8); my $tasks = 3; $pm->run_on_finish( sub { my ($pid, $exit_code) = @_; my $output = "$pid has finished with exit code $exit_code.\n"; print $output; } ); for my $task (1 .. $tasks) { if ($pm->start($task)) { sleep 120 if $task != $tasks; next; } # This is the forked process my $time = time; print "$task\n"; print "$time\n"; $pm->finish(); } $pm->wait_all_children;

    Note that I haven't tested the code.

    True laziness is hard work
Re: How to sleep before the next fork kicks off?
by kcott (Archbishop) on Jan 17, 2014 at 02:25 UTC

    G'day dr.jekyllandme,

    Firstly, there is a clear disconnect between the code sleep(1) and your description which variously has "n seconds" and "2 minutes". See the documentation for sleep and decide exactly what period you want.

    If "2 minutes" was correct, then sleep($x * 120); would be appropriate.

    From your description, you probably want to sleep() before you start().

    For finer control over the delay, use the core Time::HiRes module.

    -- Ken

Re: How to sleep before the next fork kicks off?
by zentara (Cardinal) on Jan 17, 2014 at 12:57 UTC
    If you want, you could use a non-blocking eventloop, and use a timer to do your forks. For example: Roll your own Event-loop. There are many other good eventloop modules out there, many use AnyEvent. Regardless of which eventloop system you use, all will have a timer method.

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh