File Coverage

blib/lib/IO/Framed/Write.pm
Criterion Covered Total %
statement 43 58 74.1
branch 7 12 58.3
condition 3 8 37.5
subroutine 12 15 80.0
pod 0 8 0.0
total 65 101 64.3


line stmt bran cond sub pod time code
1             package IO::Framed::Write;
2              
3 1     1   482 use strict;
  1         2  
  1         33  
4 1     1   7 use warnings;
  1         2  
  1         32  
5              
6 1     1   534 use IO::SigGuard ();
  1         2518  
  1         27  
7              
8 1     1   457 use IO::Framed::X ();
  1         3  
  1         732  
9              
10             sub new {
11 2     2 0 2630 my ( $class, $out_fh ) = @_;
12              
13 2         8 my $self = {
14             _out_fh => $out_fh,
15             _writer => \&_write_now,
16             };
17              
18 2         8 return bless $self, $class;
19             }
20              
21 0     0 0 0 sub get_write_fh { return $_[0]->{'_out_fh'} }
22              
23             sub disable_write_queue {
24 0 0 0 0 0 0 if ( $_[0]->{'_write_queue'} && @{ $_[0]->{'_write_queue'} } ) {
  0         0  
25 0         0 die 'Refuse to disable non-empty write queue!';
26             }
27              
28 0         0 $_[0]->{'_writer'} = \&_write_now;
29 0         0 return $_[0];
30             }
31              
32             sub enable_write_queue {
33 1   50 1 0 10 $_[0]->{'_write_queue'} ||= [];
34 1         2 $_[0]->{'_writer'} = \&_enqueue_write;
35 1         3 return $_[0];
36             }
37              
38             sub write {
39 65539     65539 0 143144 $_[0]->{'_writer'}->(@_);
40             }
41              
42             #======================================================================
43             #blocking
44             #======================================================================
45              
46             sub _write_now {
47 65537     65537   215205 local $!;
48              
49 65537 100       158172 IO::SigGuard::syswrite( $_[0]->{'_out_fh'}, $_[1] ) or do {
50 1         65 die IO::Framed::X->create('WriteError', $!);
51             };
52              
53 65536 50       631865 $_[2]->() if $_[2];
54              
55 65536         195443 return;
56             }
57              
58             #======================================================================
59             #non-blocking
60             #======================================================================
61              
62             sub _enqueue_write {
63 2     2   5 my $self = shift;
64              
65 2         2 push @{ $self->{'_write_queue'} }, \@_;
  2         5  
66              
67 2         5 return;
68             }
69              
70             #----------------------------------------------------------------------
71              
72             sub flush_write_queue {
73 4097     4097 0 8266 my ($self) = @_;
74              
75 4097         10253 while ( my $qi = $self->{'_write_queue'}[0] ) {
76 4097 100       7902 return 0 if !$self->_write_now_then_callback( @$qi );
77              
78 2         4 shift @{ $self->{'_write_queue'} };
  2         25  
79             }
80              
81 2         10 return 1;
82             }
83              
84             sub get_write_queue_count {
85 3     3 0 1230 my ($self) = @_;
86              
87 3         7 return 0 + @{ $self->{'_write_queue'} };
  3         16  
88             }
89              
90             sub forget_write_queue {
91 0     0 0 0 my ($self) = @_;
92              
93 0         0 my $count = @{ $self->{'_write_queue'} };
  0         0  
94              
95 0         0 @{ $self->{'_write_queue'} } = ();
  0         0  
96              
97 0         0 return $count;
98             }
99              
100             #----------------------------------------------------------------------
101              
102             sub _write_now_then_callback {
103 4097     4097   10192 local $!;
104              
105 4097   66     9690 my $wrote = IO::SigGuard::syswrite( $_[0]->{'_out_fh'}, $_[1] ) || do {
106             if ($! && !$!{'EAGAIN'} && !$!{'EWOULDBLOCK'}) {
107             die IO::Framed::X->create('WriteError', $!);
108             }
109              
110             return undef;
111             };
112              
113 2 50       939 if ($wrote == length $_[1]) {
114 2         8 $_[0]->{'_write_queue_partial'} = 0;
115 2 50       8 $_[2]->() if $_[2];
116 2         10 return 1;
117             }
118              
119             #Trim the bytes that we did send.
120 0           substr( $_[1], 0, $wrote ) = q<>;
121              
122             #This seems useful to track … ??
123 0           $_[0]->{'_write_queue_partial'} = 1;
124              
125 0           return 0;
126             }
127              
128             1;