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   1508 use strict;
  102         165  
  102         4216  
8              
9 102     102   448 use vars qw($VERSION);
  102         148  
  102         5469  
10             $VERSION = '1.367'; # NOTE - Should be #.### (three decimal places)
11              
12 102     102   557 use Errno qw(EAGAIN EWOULDBLOCK);
  102         184  
  102         23639  
13 102     102   665 use Carp qw(croak);
  102         202  
  102         33658  
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 894     894 1 3007 my $type = shift;
25 894         3408 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 894 100       2168 if (@_) {
34 16 100       51 if (@_ % 2) {
35 1         83 croak "$type requires an even number of parameters, if any";
36             }
37 15         36 my %args = @_;
38 15 100       40 if (defined $args{BlockSize}) {
39 14         62 $self->[BLOCK_SIZE] = delete $args{BlockSize};
40 14 100       260 croak "$type BlockSize must be greater than 0"
41             if ($self->[BLOCK_SIZE] <= 0);
42             }
43 14 100       72 if (keys %args) {
44 1         5 my @bad_args = sort keys %args;
45 1         85 croak "$type has unknown parameter(s): @bad_args";
46             }
47             }
48              
49 891         3211 $self;
50             }
51              
52             #------------------------------------------------------------------------------
53              
54             sub put {
55 450     450 1 3320 my ($self, $chunks) = @_;
56 450         843 my $old_queue_octets = $self->[TOTAL_OCTETS_LEFT];
57              
58             # Need to check lengths in octets, not characters.
59 102 50   102   206 BEGIN { eval { require bytes } and bytes->import; }
  102         66013  
60              
61 450         989 foreach (grep { length } @$chunks) {
  449         1377  
62 449         872 $self->[TOTAL_OCTETS_LEFT] += length;
63 449         749 push @{$self->[OUTPUT_QUEUE]}, $_;
  449         2831  
64             }
65              
66 450 100 100     3386 if ($self->[TOTAL_OCTETS_LEFT] && (!$old_queue_octets)) {
67 405         985 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
68 405         653 $self->[CURRENT_OCTETS_DONE] = 0;
69             }
70              
71 450         1631 $self->[TOTAL_OCTETS_LEFT];
72             }
73              
74             #------------------------------------------------------------------------------
75              
76             sub get {
77 2640     2640 1 14766 my ($self, $handle) = @_;
78              
79 2640         23458 my $result = sysread($handle, my $buffer = '', $self->[BLOCK_SIZE]);
80              
81             # sysread() returned a positive number of octets. Return whatever
82             # was read.
83 2640 100       11277 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 942 100       2695 if (defined $result) {
104 878         1769 $! = 0;
105 878         5525 return undef;
106             }
107              
108             # Nonfatal sysread() error. Return an empty list.
109 64 100 66     431 return [ ] if $! == EAGAIN or $! == EWOULDBLOCK;
110              
111             # fatal sysread error
112 13         54 undef;
113             }
114              
115             #------------------------------------------------------------------------------
116              
117             sub flush {
118 383     383 1 1156 my ($self, $handle) = @_;
119              
120             # Need to check lengths in octets, not characters.
121 102 50   102   43099 BEGIN { eval { require bytes } and bytes->import; }
  102         1569  
122              
123             # Reset errno in case there is nothing to write.
124             # https://rt.cpan.org/Public/Bug/Display.html?id=87721
125 383         903 $! = 0;
126              
127             # syswrite() it, like we're supposed to
128 383         518 while (@{$self->[OUTPUT_QUEUE]}) {
  800         2443  
129 435         18610 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 435 100       1925 $! = 0 if defined $wrote_count;
138              
139 435 100       1103 unless ($wrote_count) {
140 18 100 66     93 $! = 0 if $! == EAGAIN or $! == EWOULDBLOCK;
141 18         22 last;
142             }
143              
144 417         730 $self->[CURRENT_OCTETS_DONE] += $wrote_count;
145 417         699 $self->[TOTAL_OCTETS_LEFT] -= $wrote_count;
146 417 100       1033 unless ($self->[CURRENT_OCTETS_LEFT] -= $wrote_count) {
147 400         502 shift(@{$self->[OUTPUT_QUEUE]});
  400         786  
148 400 100       713 if (@{$self->[OUTPUT_QUEUE]}) {
  400         1061  
149 36         60 $self->[CURRENT_OCTETS_DONE] = 0;
150 36         75 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
151             }
152             else {
153 364         827 $self->[CURRENT_OCTETS_DONE] = $self->[CURRENT_OCTETS_LEFT] = 0;
154             }
155             }
156             }
157              
158 383         1388 $self->[TOTAL_OCTETS_LEFT];
159             }
160              
161             #------------------------------------------------------------------------------
162              
163             sub get_out_messages_buffered {
164 44     44 1 876 scalar(@{$_[0]->[OUTPUT_QUEUE]});
  44         705  
165             }
166              
167             1;
168              
169             __END__