1 # Copyright (C) 2016 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
4 # Limits the number of processes spawned
5 # This does not depend on Danga::Socket or any other external
6 # scheduling mechanism, you just need to call start and finish
8 package PublicInbox::Qspawn;
11 use PublicInbox::Spawn qw(popen_rd);
14 my ($class, $cmd, $env, $opt) = @_;
15 bless { args => [ $cmd, $env, $opt ] }, $class;
22 ($self->{rpipe}, $self->{pid}) = popen_rd(@{$self->{args}});
23 if (defined $self->{pid}) {
24 $self->{limiter}->{running}++;
28 $cb->($self->{rpipe});
33 my $limiter = $self->{limiter};
35 if (delete $self->{rpipe}) {
36 my $pid = delete $self->{pid};
37 $self->{err} = $pid == waitpid($pid, 0) ? $? :
38 "PID:$pid still running?";
39 $running = --$limiter->{running};
42 # limiter->{max} may change dynamically
43 if (($running || $limiter->{running}) < $limiter->{max}) {
44 if (my $next = shift @{$limiter->{run_queue}}) {
52 my ($self, $limiter, $cb) = @_;
53 $self->{limiter} = $limiter;
55 if ($limiter->{running} < $limiter->{max}) {
56 _do_spawn($self, $cb);
58 push @{$limiter->{run_queue}}, [ $self, $cb ];
62 package PublicInbox::Qspawn::Limiter;
67 my ($class, $max) = @_;
69 # 32 is same as the git-daemon connection limit