File Coverage

blib/lib/Proc/Forkmap.pm
Criterion Covered Total %
statement 20 63 31.7
branch 0 10 0.0
condition 0 8 0.0
subroutine 7 13 53.8
pod 4 4 100.0
total 31 98 31.6


line stmt bran cond sub pod time code
1             package Proc::Forkmap;
2 1     1   15170 use POSIX qw(:sys_wait_h);
  1         5196  
  1         6  
3 1     1   1587 use Proc::Fork;
  1         1569  
  1         6  
4 1     1   184 use Carp;
  1         6  
  1         57  
5 1     1   507 use IO::Pipe;
  1         5842  
  1         38  
6 1     1   8 use strict;
  1         2  
  1         17  
7 1     1   6 use warnings;
  1         2  
  1         22  
8 1     1   19 use 5.010;
  1         2  
9              
10             our $VERSION = '0.025';
11              
12              
13             sub new {
14 0     0 1   my $class = shift;
15 0           my $self = bless {@_}, $class;
16 0           $self->_init;
17 0           return $self;
18             }
19              
20              
21             sub _init {
22 0     0     my $self = shift;
23 0   0       $self->{max_kids} //= 4;
24 0   0       $self->{ipc} //= 0; #ipc off by default
25             }
26              
27              
28             sub max_kids {
29 0     0 1   my ($self,$n) = @_;
30 0   0       $n // return $self->{max_kids};
31 0           $self->{max_kids} = $n;
32             }
33              
34              
35             sub ipc {
36 0     0 1   my ($self,$n) = @_;
37 0   0       $n // return $self->{ipc};
38 0           $self->{ipc} = $n;
39             }
40              
41              
42             sub fmap {
43 0     0 1   my ($self,$code) = (shift,shift);
44 0           my %pids = ();
45 0           my @rs = (); #result set of child return values
46 0           my $max = $self->max_kids;
47 0           my $ipc = $self->ipc;
48 0           for my $proc (@_) {
49 0 0         my $pipe = $ipc ? IO::Pipe->new : {}; #put this in your pipe, and smoke it
50             #max kids?
51 0           while ($max == keys %pids) {
52             #free a spot in queue when a process completes
53 0           for my $pid (keys %pids) {
54 0 0         if (my $kid = waitpid($pid, WNOHANG)) {
55 0           delete $pids{$kid};
56 0           last;
57             }
58             }
59             }
60            
61             run_fork { #processes fork here
62             parent {
63 0           $| = 1;
64 0           my $kid = shift;
65 0           $pids{$kid}++;
66 0 0         if ($ipc) {
67 0           $pipe->reader();
68 0           while(<$pipe>) {
69 0           push @rs,$_;
70             }
71             }
72             }
73             child {
74 0           $| = 1;
75 0           my $rs = $code->($proc);
76 0 0         if ($ipc) {
77 0           $pipe->writer();
78 0 0         print $pipe $rs if defined $rs;
79             }
80 0           exit;
81             }
82             error {
83 0           die "error: couldn't fork";
84             }
85 0     0     };
  0            
86             }
87            
88 0           1 while (wait() != -1); #wait for the stragglers to finish
89 0           return @rs;
90             }
91              
92              
93              
94              
95             1;
96              
97             __END__