File Coverage

blib/lib/POE/Driver/SysRW.pm
Criterion Covered Total %
statement 70 70 100.0
branch 30 32 93.7
condition 7 9 77.7
subroutine 11 11 100.0
pod 5 5 100.0
total 123 127 96.8


line stmt bran cond sub pod time code
1             # Copyright 1998-2013 Rocco Caputo . All rights
2             # reserved. This program is free software; you can redistribute it
3             # and/or modify it under the same terms as Perl itself.
4              
5             package POE::Driver::SysRW;
6              
7 102     102   1204 use strict;
  102         154  
  102         3527  
8              
9 102     102   436 use vars qw($VERSION);
  102         147  
  102         4528  
10             $VERSION = '1.365'; # NOTE - Should be #.### (three decimal places)
11              
12 102     102   440 use Errno qw(EAGAIN EWOULDBLOCK);
  102         178  
  102         5104  
13 102     102   504 use Carp qw(croak);
  102         131  
  102         29345  
14              
15             sub OUTPUT_QUEUE () { 0 }
16             sub CURRENT_OCTETS_DONE () { 1 }
17             sub CURRENT_OCTETS_LEFT () { 2 }
18             sub BLOCK_SIZE () { 3 }
19             sub TOTAL_OCTETS_LEFT () { 4 }
20              
21             #------------------------------------------------------------------------------
22              
23             sub new {
24 890     890 1 3294 my $type = shift;
25 890         2836 my $self = bless [
26             [ ], # OUTPUT_QUEUE
27             0, # CURRENT_OCTETS_DONE
28             0, # CURRENT_OCTETS_LEFT
29             65536, # BLOCK_SIZE
30             0, # TOTAL_OCTETS_LEFT
31             ], $type;
32              
33 890 100       2095 if (@_) {
34 16 100       45 if (@_ % 2) {
35 1         84 croak "$type requires an even number of parameters, if any";
36             }
37 15         38 my %args = @_;
38 15 100       40 if (defined $args{BlockSize}) {
39 14         51 $self->[BLOCK_SIZE] = delete $args{BlockSize};
40 14 100       204 croak "$type BlockSize must be greater than 0"
41             if ($self->[BLOCK_SIZE] <= 0);
42             }
43 14 100       61 if (keys %args) {
44 1         3 my @bad_args = sort keys %args;
45 1         89 croak "$type has unknown parameter(s): @bad_args";
46             }
47             }
48              
49 887         2965 $self;
50             }
51              
52             #------------------------------------------------------------------------------
53              
54             sub put {
55 426     426 1 3157 my ($self, $chunks) = @_;
56 426         742 my $old_queue_octets = $self->[TOTAL_OCTETS_LEFT];
57              
58             # Need to check lengths in octets, not characters.
59 102 50   102   184 BEGIN { eval { require bytes } and bytes->import; }
  102         20408  
60              
61 426         1167 foreach (grep { length } @$chunks) {
  425         1223  
62 425         776 $self->[TOTAL_OCTETS_LEFT] += length;
63 425         456 push @{$self->[OUTPUT_QUEUE]}, $_;
  425         1528  
64             }
65              
66 426 100 100     3134 if ($self->[TOTAL_OCTETS_LEFT] && (!$old_queue_octets)) {
67 383         649 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
68 383         495 $self->[CURRENT_OCTETS_DONE] = 0;
69             }
70              
71 426         1464 $self->[TOTAL_OCTETS_LEFT];
72             }
73              
74             #------------------------------------------------------------------------------
75              
76             sub get {
77 2569     2569 1 13237 my ($self, $handle) = @_;
78              
79 2569         16761 my $result = sysread($handle, my $buffer = '', $self->[BLOCK_SIZE]);
80              
81             # sysread() returned a positive number of octets. Return whatever
82             # was read.
83 2569 100       10378 return [ $buffer ] if $result;
84              
85             # 18:01 sysread() clears $! when it returns 0 for eof?
86             # 18:01 nobody clears $!
87             # 18:01 returning 0 is not an error
88             # 18:01 returning -1 is an error, and sets $!
89             # 18:01 eof is not an error. :)
90              
91             # 18:21 perl -wle '$!=1; warn "\$!=",$!+0; \
92             # warn "sysread=",sysread(STDIN,my $x="",100); \
93             # die "\$!=",$!+0' < /dev/null
94             # 18:23 $!=1 at foo line 1.
95             # 18:23 sysread=0 at foo line 1.
96             # 18:23 $!=0 at foo line 1.
97             # 18:23 5.6.0 on Darwin.
98             # 18:23 Same, 5.6.1 on fbsd 4.4-stable.
99             # read(2) must be clearing errno or something.
100              
101             # sysread() returned 0, signifying EOF. Although $! is magically
102             # set to 0 on EOF, it may not be portable to rely on this.
103 883 100       2504 if (defined $result) {
104 823         1526 $! = 0;
105 823         3788 return undef;
106             }
107              
108             # Nonfatal sysread() error. Return an empty list.
109 60 100 66     288 return [ ] if $! == EAGAIN or $! == EWOULDBLOCK;
110              
111             # fatal sysread error
112 9         33 undef;
113             }
114              
115             #------------------------------------------------------------------------------
116              
117             sub flush {
118 350     350 1 1249 my ($self, $handle) = @_;
119              
120             # Need to check lengths in octets, not characters.
121 102 50   102   29950 BEGIN { eval { require bytes } and bytes->import; }
  102         1074  
122              
123             # Reset errno in case there is nothing to write.
124             # https://rt.cpan.org/Public/Bug/Display.html?id=87721
125 350         825 $! = 0;
126              
127             # syswrite() it, like we're supposed to
128 350         400 while (@{$self->[OUTPUT_QUEUE]}) {
  731         1708  
129 399         11777 my $wrote_count = syswrite(
130             $handle,
131             $self->[OUTPUT_QUEUE]->[0],
132             $self->[CURRENT_OCTETS_LEFT],
133             $self->[CURRENT_OCTETS_DONE],
134             );
135              
136             # Errors only count if syswrite() failed.
137 399 100       1115 $! = 0 if defined $wrote_count;
138              
139 399 100       756 unless ($wrote_count) {
140 18 100 66     81 $! = 0 if $! == EAGAIN or $! == EWOULDBLOCK;
141 18         17 last;
142             }
143              
144 381         539 $self->[CURRENT_OCTETS_DONE] += $wrote_count;
145 381         553 $self->[TOTAL_OCTETS_LEFT] -= $wrote_count;
146 381 100       847 unless ($self->[CURRENT_OCTETS_LEFT] -= $wrote_count) {
147 364         394 shift(@{$self->[OUTPUT_QUEUE]});
  364         736  
148 364 100       593 if (@{$self->[OUTPUT_QUEUE]}) {
  364         816  
149 33         40 $self->[CURRENT_OCTETS_DONE] = 0;
150 33         55 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
151             }
152             else {
153 331         680 $self->[CURRENT_OCTETS_DONE] = $self->[CURRENT_OCTETS_LEFT] = 0;
154             }
155             }
156             }
157              
158 350         1030 $self->[TOTAL_OCTETS_LEFT];
159             }
160              
161             #------------------------------------------------------------------------------
162              
163             sub get_out_messages_buffered {
164 34     34 1 1161 scalar(@{$_[0]->[OUTPUT_QUEUE]});
  34         357  
165             }
166              
167             1;
168              
169             __END__