File Coverage

blib/lib/Parallel/SubArray.pm
Criterion Covered Total %
statement 55 55 100.0
branch 12 14 85.7
condition 4 5 80.0
subroutine 5 5 100.0
pod 1 1 100.0
total 77 80 96.2


line stmt bran cond sub pod time code
1             package Parallel::SubArray;
2             require v5.8.6;
3             our $VERSION = 0.6;
4 15     15   989565 use strict;
  15         45  
  15         660  
5 15     15   19065 use Storable qw(store_fd fd_retrieve);
  15         79680  
  15         1500  
6 15     15   150 use Exporter 'import';
  15         135  
  15         10905  
7             our @EXPORT_OK = qw(par);
8              
9             sub par {
10 21     21 1 867 my( $timeout ) = @_;
11             sub {
12 29     29   225717 my @subs = @{ shift(@_) };
  29         159  
13 29         46 my %rets;
14 29         47 my $c = 0;
15 29         104 for my $sub ( @subs ) {
16 105         183 $c++;
17 105         142 my( $parent_w, $child_r );
18 105         6732 pipe( $child_r, $parent_w );
19 105         4129 select((select($parent_w ), $| = 1)[0]);
20 105 100       218992 if( my $pid = fork ) {
21 87         4641 close $parent_w;
22 87         10541 $rets{ $pid } = { fd => $child_r,
23             ord => $c
24             };
25             } else {
26 18 50       1679 die "Cannot fork: $!" unless defined $pid;
27 18         1200 close $child_r;
28             my $exit = sub {
29 14         138 my( $save_val, $exit_val ) = @_;
30 14         726 store_fd $save_val, $parent_w;
31 14         5257 close $parent_w;
32 14         9114 exit $exit_val;
33 18         3204 };
34 18         5690 local $SIG{ALRM} = sub { $exit->( ['TIMEOUT'], 1 ) };
  2         6000236  
35 18   100     1753 alarm( $timeout || 0 );
36 18         471 my $ret = eval{ $sub->() };
  18         958  
37 12         8002486 my $err = $@;
38 12         228 alarm( 0 );
39 12 100       317 $exit->( [$err], 1 ) if $err;
40 10         258 $exit->( $ret , 0 );
41             }
42             }
43 11         308 while(1) {
44 60         33412740 my $pid = wait();
45 60         61792 my $err = $?;
46 60 100 66     1649 last if( $pid == -1 or not @subs );
47 49 50       482 next if not exists $rets{ $pid };
48 49 100       343 if( $err ) {
49 18         502 $rets{ $pid }->{err} = fd_retrieve( $rets{ $pid }->{fd} )->[0];
50             } else {
51 31         818 $rets{ $pid }->{val} = fd_retrieve( $rets{ $pid }->{fd} );
52             }
53 49         5279 close $rets{ $pid }->{fd};
54 49         218 pop @subs;
55             }
56             my $r = sub {
57 12         101 my( $key ) = @_;
58             # can be optimized
59 54         427 [ map { $rets{$_}->{ $key } }
  62         276  
60 12         312 sort { $rets{$a}->{ord} <=> $rets{$b}->{ord} }
61             keys %rets
62             ];
63 11         217 };
64 11 100       178 return wantarray ? ( $r->('val'), $r->('err') ) : $r->('val');
65             }
66 21         663 }
67              
68             1;
69             __END__