| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package IO::Pipe::Producer; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 7 |  |  | 7 |  | 104097 | use 5.010001; | 
|  | 7 |  |  |  |  | 21 |  | 
|  | 7 |  |  |  |  | 217 |  | 
| 4 | 7 |  |  | 7 |  | 21 | use strict; | 
|  | 7 |  |  |  |  | 7 |  | 
|  | 7 |  |  |  |  | 203 |  | 
| 5 | 7 |  |  | 7 |  | 28 | use warnings; | 
|  | 7 |  |  |  |  | 28 |  | 
|  | 7 |  |  |  |  | 154 |  | 
| 6 | 7 |  |  | 7 |  | 42 | use Carp; | 
|  | 7 |  |  |  |  | 7 |  | 
|  | 7 |  |  |  |  | 539 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | our @ISA = qw(IO::Pipe); | 
| 9 | 7 |  |  | 7 |  | 28 | use base qw(IO::Pipe); | 
|  | 7 |  |  |  |  | 7 |  | 
|  | 7 |  |  |  |  | 3262 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | our $VERSION = '2.01'; | 
| 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 | 3239186 | my $class = shift(@_); | 
| 41 |  |  |  |  |  |  | #Instantiate an instance of the super class | 
| 42 | 27 |  |  |  |  | 249 | my $self = $class->SUPER::new(); | 
| 43 |  |  |  |  |  |  | #Bless the instantiation into this class so we can call our own methods | 
| 44 | 27 |  |  |  |  | 3962 | bless($self,$class); | 
| 45 |  |  |  |  |  |  | #If a subroutine call was supplied | 
| 46 | 27 | 100 |  |  |  | 147 | if(scalar(@_)) | 
| 47 |  |  |  |  |  |  | { | 
| 48 |  |  |  |  |  |  | #Declare file handles for STDOUT and STDERR | 
| 49 | 9 |  |  |  |  | 23 | my($fh,$eh); | 
| 50 |  |  |  |  |  |  | #If new was called in list context | 
| 51 | 9 | 100 |  |  |  | 61 | if(wantarray) | 
| 52 |  |  |  |  |  |  | { | 
| 53 |  |  |  |  |  |  | #Fill the handles with the outputs from the subroutine | 
| 54 | 4 |  |  |  |  | 24 | ($fh,$eh) = $self->getSubroutineProducer(@_); | 
| 55 |  |  |  |  |  |  | #Return blessed referents to the file handles | 
| 56 | 3 |  |  |  |  | 210 | return(bless($fh,$class),bless($eh,$class)); | 
| 57 |  |  |  |  |  |  | } | 
| 58 |  |  |  |  |  |  | #Fill the STDOUT handle with the output from the subroutine | 
| 59 | 5 |  |  |  |  | 35 | $fh = $self->getSubroutineProducer(@_); | 
| 60 |  |  |  |  |  |  | #Return blessed referent to the STDOUT handle | 
| 61 | 4 |  |  |  |  | 180 | return(bless($fh,$class)); | 
| 62 |  |  |  |  |  |  | } | 
| 63 |  |  |  |  |  |  | #Return a blessed referent of the object hash | 
| 64 | 18 | 50 |  |  |  | 56 | if(wantarray) | 
| 65 | 0 |  |  |  |  | 0 | {return($self,bless($class->SUPER::new(),$class))} | 
| 66 | 18 |  |  |  |  | 41 | 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 | 252 | my $self         = shift; | 
| 76 | 27 |  |  |  |  | 37 | my $producer_sub = shift; | 
| 77 | 27 |  |  |  |  | 85 | my @params       = @_; | 
| 78 | 27 |  |  |  |  | 42 | my($pid,$error); | 
| 79 |  |  |  |  |  |  |  | 
| 80 | 27 | 50 | 33 |  |  | 258 | 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 |  |  |  |  | 97 | my $stdout_pipe = $self->SUPER::new(); | 
| 92 | 27 |  |  |  |  | 4380 | my($stderr_pipe); | 
| 93 | 27 | 100 |  |  |  | 102 | $stderr_pipe = $self->SUPER::new() if(wantarray); | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  | #Fork off the Producer | 
| 96 | 27 | 50 |  |  |  | 18354 | if(defined($pid = fork())) | 
| 97 |  |  |  |  |  |  | { | 
| 98 | 27 | 100 |  |  |  | 256 | if($pid) | 
| 99 |  |  |  |  |  |  | { | 
| 100 |  |  |  |  |  |  | ## | 
| 101 |  |  |  |  |  |  | ## Parent | 
| 102 |  |  |  |  |  |  | ## | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | #Create a read file handle | 
| 105 | 21 |  |  |  |  | 987 | $stdout_pipe->reader(); | 
| 106 | 21 | 100 |  |  |  | 3412 | $stderr_pipe->reader() if(wantarray); | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | #Return the read file handle to the consumer | 
| 109 | 21 | 100 |  |  |  | 529 | if(wantarray) | 
| 110 | 9 |  |  |  |  | 390 | {return(bless($stdout_pipe,ref($self)), | 
| 111 |  |  |  |  |  |  | bless($stderr_pipe,ref($self)))} | 
| 112 | 12 |  |  |  |  | 370 | 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 |  |  |  |  | 575 | $stdout_pipe->writer(); | 
| 122 | 6 |  |  |  |  | 829 | $stdout_pipe->autoflush; | 
| 123 | 6 | 100 |  |  |  | 1038 | $stderr_pipe->writer()  if(defined($stderr_pipe)); | 
| 124 | 6 | 100 |  |  |  | 179 | $stderr_pipe->autoflush if(defined($stderr_pipe)); | 
| 125 |  |  |  |  |  |  |  | 
| 126 |  |  |  |  |  |  | #Redirect standard outputs to the pipes or kill the child | 
| 127 | 6 | 50 | 66 |  |  | 108 | if(!open(STDOUT,">&",\${$stdout_pipe})) | 
|  | 6 | 50 |  |  |  | 544 |  | 
| 128 | 3 |  |  |  |  | 51 | { | 
| 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 |  |  |  |  | 79 | $producer_sub->(@params); | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | #Close the writer pipes | 
| 150 | 6 |  |  |  |  | 246 | close($stdout_pipe); | 
| 151 | 6 | 100 |  |  |  | 68 | close($stderr_pipe) if(defined($stderr_pipe)); | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | #Successfully exiting the child process | 
| 154 | 6 |  |  |  |  | 1190 | 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 | 142 | my $self = shift; | 
| 170 | 5 |  |  | 2 |  | 63 | return($self->getSubroutineProducer(sub {system(@_)},@_)); | 
|  | 2 |  |  |  |  | 6945 |  | 
| 171 |  |  |  |  |  |  | } | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | 1; | 
| 175 |  |  |  |  |  |  | __END__ |