]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/Qspawn.pm
Merge branch 'thread-view-skel'
[public-inbox.git] / lib / PublicInbox / Qspawn.pm
1 # Copyright (C) 2016 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 package PublicInbox::Qspawn;
4 use strict;
5 use warnings;
6 use PublicInbox::Spawn qw(popen_rd);
7 our $LIMIT = 1;
8 my $running = 0;
9 my @run_queue;
10
11 sub new ($$$;) {
12         my ($class, $cmd, $env, $opt) = @_;
13         bless { args => [ $cmd, $env, $opt ] }, $class;
14 }
15
16 sub _do_spawn {
17         my ($self, $cb) = @_;
18         my $err;
19         ($self->{rpipe}, $self->{pid}) = popen_rd(@{$self->{args}});
20         if (defined $self->{pid}) {
21                 $running++;
22         } else {
23                 $self->{err} = $!;
24         }
25         $cb->($self->{rpipe});
26 }
27
28 sub finish ($) {
29         my ($self) = @_;
30         if (delete $self->{rpipe}) {
31                 my $pid = delete $self->{pid};
32                 $self->{err} = $pid == waitpid($pid, 0) ? $? :
33                                 "PID:$pid still running?";
34                 $running--;
35         }
36         if (my $next = shift @run_queue) {
37                 _do_spawn(@$next);
38         }
39         $self->{err};
40 }
41
42 sub start ($$) {
43         my ($self, $cb) = @_;
44
45         if ($running < $LIMIT) {
46                 _do_spawn($self, $cb);
47         } else {
48                 push @run_queue, [ $self, $cb ];
49         }
50 }
51
52 1;