File Coverage

blib/lib/IO/Pipe/Producer.pm
Criterion Covered Total %
statement 56 71 78.8
branch 23 28 82.1
condition 3 6 50.0
subroutine 9 9 100.0
pod 1 3 33.3
total 92 117 78.6


line stmt bran cond sub pod time code
1             package IO::Pipe::Producer;
2              
3 7     7   192626 use 5.012003;
  7         28  
  7         245  
4 7     7   35 use strict;
  7         14  
  7         245  
5 7     7   28 use warnings;
  7         49  
  7         259  
6 7     7   35 use Carp;
  7         7  
  7         749  
7              
8             our @ISA = qw(IO::Pipe);
9 7     7   42 use base qw(IO::Pipe);
  7         14  
  7         6769  
10              
11             our $VERSION = '2.0';
12              
13             #NOTICE
14             #
15             #This software and ancillary information (herein called "SOFTWARE") called
16             #Producer.pm is made available under the terms described here. The
17             #SOFTWARE has been approved for release with associated LA-CC number
18             #LA-CC-05-060.
19             #
20             #Unless otherwise indicated, this software has been authored by an employee or
21             #employees of the University of California, operator of the Los Alamos National
22             #Laboratory under Contract No. W-7405-ENG-36 with the U.S. Department of
23             #Energy. The U.S. government has rights to use, reproduce, and distribute this
24             #SOFTWARE. The public may copy, distribute, prepare derivative works and
25             #publicly display this SOFTWARE without charge, provided that this notice and
26             #any statement of authorship are reproduced on all copies. Neither the
27             #government nor the university makes any warranty, express or implied, or
28             #assumes any liability or responsibility for the use of this SOFTWARE.
29             #
30             #If SOFTWARE is modified to produce derivative works, such modified SOFTWARE
31             #should be clearly marked, so as not to confuse it with the version available
32             #from LANL.
33              
34              
35             #Constructor
36              
37             sub new
38             {
39             #Get the class name
40 27     27 1 5351972 my $class = shift(@_);
41             #Instantiate an instance of the super class
42 27         388 my $self = $class->SUPER::new();
43             #Bless the instantiation into this class so we can call our own methods
44 27         3950 bless($self,$class);
45             #If a subroutine call was supplied
46 27 100       169 if(scalar(@_))
47             {
48             #Declare file handles for STDOUT and STDERR
49 9         48 my($fh,$eh);
50             #If new was called in list context
51 9 100       122 if(wantarray)
52             {
53             #Fill the handles with the outputs from the subroutine
54 4         52 ($fh,$eh) = $self->getSubroutineProducer(@_);
55             #Return blessed referents to the file handles
56 3         252 return(bless($fh,$class),bless($eh,$class));
57             }
58             #Fill the STDOUT handle with the output from the subroutine
59 5         40 $fh = $self->getSubroutineProducer(@_);
60             #Return blessed referent to the STDOUT handle
61 4         396 return(bless($fh,$class));
62             }
63             #Return a blessed referent of the object hash
64 18 50       70 if(wantarray)
65 0         0 {return($self,bless($class->SUPER::new(),$class))}
66 18         105 return($self);
67             }
68              
69              
70              
71             #This method is also a constructor
72             sub getSubroutineProducer
73             {
74             #Read in subroutine reference
75 27     27 0 380 my $self = shift;
76 27         42 my $producer_sub = shift;
77 27         98 my @params = @_;
78 27         49 my($pid,$error);
79              
80 27 50 33     352 if(!defined($producer_sub) || ref($producer_sub) ne 'CODE')
81             {
82 0         0 $error = "ERROR:Producer.pm:getSubroutineProducer:A referenced " .
83             "subroutine is required as the first argument to " .
84             "getSubroutineProducer.";
85 0         0 $Producer::errstr = $error;
86 0         0 carp($error);
87 0         0 return(undef);
88             }
89              
90             #Create a pipe
91 27         94 my $stdout_pipe = $self->SUPER::new();
92 27         6434 my($stderr_pipe);
93 27 100       130 $stderr_pipe = $self->SUPER::new() if(wantarray);
94              
95             #Fork off the Producer
96 27 50       46604 if(defined($pid = fork()))
97             {
98 27 100       577 if($pid)
99             {
100             ##
101             ## Parent
102             ##
103              
104             #Create a read file handle
105 21         1763 $stdout_pipe->reader();
106 21 100       5179 $stderr_pipe->reader() if(wantarray);
107              
108             #Return the read file handle to the consumer
109 21 100       681 if(wantarray)
110 9         520 {return(bless($stdout_pipe,ref($self)),
111             bless($stderr_pipe,ref($self)))}
112 12         444 return(bless($stdout_pipe,ref($self)));
113             }
114             else
115             {
116             ##
117             ## Child
118             ##
119              
120             #Create a write file handle for the Producer
121 6         1280 $stdout_pipe->writer();
122 6         2264 $stdout_pipe->autoflush;
123 6 100       1926 $stderr_pipe->writer() if(defined($stderr_pipe));
124 6 100       227 $stderr_pipe->autoflush if(defined($stderr_pipe));
125              
126             #Redirect standard outputs to the pipes or kill the child
127 6 50 66     161 if(!open(STDOUT,">&",\${$stdout_pipe}))
  6 50       1060  
128 3         116 {
129 0         0 $error = "ERROR:Producer.pm:getSubroutineProducer:Can't " .
130             "redirect stdout to pipe: [" .
131             select($stdout_pipe) .
132             "]. $!";
133 0         0 $Producer::errstr = $error;
134 0         0 croak($error);
135             }
136             elsif(defined($stderr_pipe) && !open(STDERR,">&",\${$stderr_pipe}))
137             {
138 0         0 $error = "ERROR:Producer.pm:getSubroutineProducer:Can't " .
139             "redirect stderr to pipe: [" .
140             select($stderr_pipe) .
141             "]. $!";
142 0         0 $Producer::errstr = $error;
143 0         0 croak($error);
144             }
145              
146             #Call the subroutine passed in (ignore it's return value)
147 6         279 $producer_sub->(@params);
148              
149             #Close the writer pipes
150 6         520 close($stdout_pipe);
151 6 100       95 close($stderr_pipe) if(defined($stderr_pipe));
152              
153             #Successfully exiting the child process
154 6         3228 exit(0);
155             }
156             }
157             else
158             {
159 0         0 $error = "ERROR:Producer.pm:getSubroutineProducer:fork() didn't work!";
160 0         0 $Producer::errstr = $error;
161 0         0 carp($error);
162 0         0 return(undef);
163             }
164             }
165              
166              
167             sub getSystemProducer
168             {
169 5     5 0 183 my $self = shift;
170 5     2   59 return($self->getSubroutineProducer(sub {system(@_)},@_));
  2         18605  
171             }
172              
173              
174             1;
175             __END__