ibm1620 has asked for the wisdom of the Perl Monks concerning the following question:

At one point use threads; was recommended for starting multiple asynchronous execution.

http://stackoverflow.com/a/9254974/522385

The CPAN documentation for Perl v5.22 indicates it's deprecated, and indeed my v5.16 doesn't have support compiled in: "This Perl not built to support threads"

I want my Perl script to start several mysql commands running concurrently, and wait for them all to finish. I liked the simplicity of the threads module -- What is the currently-accepted best practice for this?

Replies are listed 'Best First'.
Re: Multiple asynchronous execution of commands
by BrowserUk (Patriarch) on Jan 22, 2016 at 20:14 UTC

    Starting a process, in order to wait for another process, when the main process will still have to wait for the waiting process, is more than a little convoluted.

    It also makes life difficult in that the main program doesn't have access to the pid of the subprocess it wants to run/monitor/control, only the pid for the waiting process that it doesn't really want.

    threads certainly simplify the scenario, and despite the "deprecation", they still work fine, provided they are enabled at build time.

    But, either way, often the simplest of all is to use the piped open, which is asynchronous and returns the pid of the process you want to control/monitor.

    The only things to be careful of is if the process you're running produces a lot of output; in which case it will fill the output buffer and block until you read some data from the other end of the pipe periodically to prevent that.

    It gets a little more complex if you need the output from multiple processes, as you need to multiplex that reading somehow. (Eg. IO::Select)

    If you don't need the output, then redirecting it to null is a possibility, but that reintroduces the problem of the intermediate process (the shell to do the redirection).


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
      I wonder if I was ambiguous - what I want to do is have the main program start several processes, and wait for them all to finish. Not "have the main program start a process that, in turn, starts several processes and waits for them ...". Unless I'm missing a subtlety, I don't think what I'm proposing involves more than a parent process waiting directly upon several child processes.
        Unless I'm missing a subtlety, I don't think what I'm proposing involves more than a parent process waiting directly upon several child processes.

        The "process to wait for a process" arises when you use modules like Parallel::ForkManager as a substitute for threading, as someone else suggested.

        That is, you cannot ask P::FM to start the processes you want directly. Instead, it forks your current program and you then start the process you want to start from that subprocess, whilst the main process continues. It's a messy solution at best.

        The piped-open is asynchronous, thus you can use it to start multiple concurrent processes directly from your main process without problem.

        However, most times you don't only want to start the subprocess, but also monitor (is it still running?) and control (eg. kill it if it takes to long) and at least, eventually receive information that it has ended successfully or otherwise.

        For all of these things, having the pid of the actual subprocess started is necessary; and the piped-open gives you that control. It also gives you access to that subprocesses output; which is easily and economically discarded if not required.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Multiple asynchronous execution of commands
by choroba (Cardinal) on Jan 22, 2016 at 19:38 UTC
    threads are not deprecated, they're discouraged. It just means the folks in IRC got fed up with newbies constantly asking how to use threads. If you need an interpreter with thread support, you can compile it yourself, or use perlbrew.
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      Thanks for pointing out the distinction. Unfortunately, I'm stuck with whatever build of Perl the operations staff compiles. We're currently on v5.10, which does have thread support built in, but if a future release comes along that omits it by default, I may be out of luck.

      (http://perldoc.perl.org/perlpolicy.html#discouraged states that discouraged features are considered to be "mistakes" that may one day be deprecated.)
        Unfortunately, I'm stuck with whatever build of Perl the operations staff compiles. We're currently on v5.10, which does have thread support built in, but if a future release comes along that omits it by default, I may be out of luck.

        Version 5.10 is more than 8 years old. If your ops team keep on this path you'll have a good 8 years to plan your migration away from threads in the unlikely event that it is removed from perl.

        [perldoc] states that discouraged features are considered to be "mistakes" that may one day be deprecated.

        That is true. However, there would be a serious outcry if threads were removed from Perl5, given the amount of code which requires it. And deprecated != removed, so even in a worst-case scenario you'll have plenty of warning.

Re: Multiple asynchronous execution of commands
by stevieb (Canon) on Jan 22, 2016 at 17:53 UTC
Re: Multiple asynchronous execution of commands
by mneme (Initiate) on Jan 25, 2016 at 22:18 UTC
    You can also just fork + wait.

    Note that if you're using a single connection to mysql, with threads our without them, you can't start multiple simultaneous commands through a single connection; db connections don't work that way (unless mysql has an extended sql command set to support background jobs, anyway; without getting stupid complicated I don't see one, though)! But you can open the connection in the subprocesses (easier to do with full processes, not threads), and run the command in each.

    It doesn't seem like you're looking for data back from the subprocesses, which makes this pretty simple, for instance:

    #!/usr/bin/perl use feature ':5.18'; my @commands = (sub {say "hi"},sub {say "there"},sub {sleep 2},sub {ex +ec("echo bye")}); my %jobs; for(@commands) { my $pid = fork(); die "bad fork" unless defined $pid; if($pid==0) { # child eval { $_->(); }; $@ and die "cmd failed: $@"; exit ($? ? $? : 0); } # parent if($pid<=0) { warn "job $_ failed ($pid): $!"; } else { $jobs{$pid}={cmd=>$_, status => "running"} } # here is where you can check for having too many jobs running if # you want to set a limit and wait for them. } # now wait for my jobs until I'm out of children. while(%jobs) { my $pid = wait(); last if($pid == -1); # no children = no more waiting next unless exists $jobs{$pid}; #if it's not a job we're watching, w +e don't care. #do any special handling, then... my $job = $jobs{$pid}; say "$pid ($job->{cmd}) finished with code $?"; delete $jobs{$pid}; } #continue on with the program. say "done";