File Coverage

blib/lib/Proc/Hevy/Writer.pm
Criterion Covered Total %
statement 64 67 95.5
branch 25 36 69.4
condition 3 6 50.0
subroutine 12 12 100.0
pod 4 4 100.0
total 108 125 86.4


line stmt bran cond sub pod time code
1             package Proc::Hevy::Writer;
2              
3 25     25   147 use strict;
  25         42  
  25         899  
4 25     25   132 use warnings;
  25         50  
  25         677  
5              
6 25     25   173 use Carp;
  25         132  
  25         1703  
7 25     25   142 use Errno qw( EWOULDBLOCK );
  25         50  
  25         1063  
8 25     25   159 use IO::Pipe;
  25         52  
  25         698  
9 25     25   143 use POSIX ();
  25         50  
  25         21602  
10              
11              
12             sub new {
13 67     67 1 227 my ( $class, $name, $buffer ) = @_;
14              
15 67         122 my $pipe;
16 67 100 66     536 $pipe = IO::Pipe->new
17             if defined $buffer and ref $buffer ne 'GLOB';
18              
19 67         2911 bless { name => $name, buffer => $buffer, pipe => $pipe }, $class;
20             }
21              
22             sub child {
23 20     20 1 340 my ( $self, $std_h, $fileno ) = @_;
24              
25 20         253 my $handle;
26              
27 20 100       1448 if( defined $self->{pipe} ) {
    50          
28 4         198 $handle = $self->{pipe}->reader;
29             }
30             elsif( ref $self->{buffer} eq 'GLOB' ) {
31 0         0 $handle = $self->{buffer};
32             }
33             else {
34 16 50       4323 open $handle, '<', '/dev/null'
35             or confess "$self->{name}: open: /dev/null: $!\n";
36             }
37              
38 20 50 33     7346 POSIX::dup2( $handle->fileno, $fileno )
39             or confess "$self->{name}: dup2: $!\n"
40             if $std_h != $handle;
41             }
42              
43             sub parent {
44 47     47 1 259 my ( $self, $select ) = @_;
45              
46 47 100       990 unless( defined $self->{pipe} ) {
47 37 50       202 delete $self->{buffer}
48             if defined $self->{buffer};
49              
50 37         843 return;
51             }
52              
53 10         244 $self->{scratch} = '';
54              
55 10         325 my $handle = $self->{pipe}->writer;
56 10         2197 $handle->blocking( 0 );
57              
58 10         198 $select->add( $handle );
59 10         1168 $self->{select} = $select;
60              
61 10         298 return ( $handle, $self );
62             }
63              
64             sub write {
65 32     32 1 52 my ( $self ) = @_;
66              
67 32         72 my $handle = $self->{pipe};
68              
69 32 50       112 if( length( $self->{scratch} ) == 0 ) {
70 32         203 my $scratch = $self->_unpack;
71              
72 32 100       96 unless( defined $scratch ) {
73 10         98 $self->{select}->remove( $handle );
74 10 50       643 $handle->close
75             or confess "$self->{name}: close: $!\n";
76 10         605 return;
77             }
78              
79 22         48 $self->{scratch} = $scratch;
80             }
81              
82 22         166 $self->_flush;
83             }
84              
85             sub _unpack {
86 32     32   53 my ( $self ) = @_;
87              
88 32         75 my $ref = ref $self->{buffer};
89              
90 32 100       124 return delete $self->{buffer}
91             if $ref eq '';
92              
93 24         199 my $data;
94              
95 24 100       169 if( $ref eq 'ARRAY' ) {
    50          
96 16         28 $data = shift @{ $self->{buffer} };
  16         141  
97             }
98             elsif( $ref eq 'CODE' ) {
99 8         92 $data = $self->{buffer}->();
100             }
101             else {
102 0         0 confess "$self->{name}: API error\n";
103             }
104              
105 24 100       270 $data .= defined $\ ? $\ : "\n"
    100          
106             if defined $data;
107              
108 24         72 return $data;
109             }
110              
111             sub _flush {
112 22     22   37 my ( $self ) = @_;
113              
114             return
115 22 50       74 unless length $self->{scratch};
116              
117 22         32 my $handle = $self->{pipe};
118 22         308 my $rc = $handle->syswrite( $self->{scratch} );
119              
120 22 50       557 if( not defined $rc ) {
121 0 0       0 confess "$self->{name}: syswrite: $!\n"
122             if $! != EWOULDBLOCK;
123             }
124             else {
125 22         319 substr( $self->{scratch}, 0, $rc ) = '';
126             }
127             }
128              
129              
130             1
131             __END__