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 103     103   1074 use strict;
  103         126  
  103         3457  
8              
9 103     103   390 use vars qw($VERSION);
  103         114  
  103         4188  
10             $VERSION = '1.366'; # NOTE - Should be #.### (three decimal places)
11              
12 103     103   430 use Errno qw(EAGAIN EWOULDBLOCK);
  103         160  
  103         4281  
13 103     103   445 use Carp qw(croak);
  103         125  
  103         29774  
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 922     922 1 3583 my $type = shift;
25 922         2869 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 922 100       1928 if (@_) {
34 16 100       80 if (@_ % 2) {
35 1         109 croak "$type requires an even number of parameters, if any";
36             }
37 15         45 my %args = @_;
38 15 100       47 if (defined $args{BlockSize}) {
39 14         65 $self->[BLOCK_SIZE] = delete $args{BlockSize};
40 14 100       217 croak "$type BlockSize must be greater than 0"
41             if ($self->[BLOCK_SIZE] <= 0);
42             }
43 14 100       70 if (keys %args) {
44 1         5 my @bad_args = sort keys %args;
45 1         98 croak "$type has unknown parameter(s): @bad_args";
46             }
47             }
48              
49 919         2858 $self;
50             }
51              
52             #------------------------------------------------------------------------------
53              
54             sub put {
55 462     462 1 3434 my ($self, $chunks) = @_;
56 462         707 my $old_queue_octets = $self->[TOTAL_OCTETS_LEFT];
57              
58             # Need to check lengths in octets, not characters.
59 103 50   103   183 BEGIN { eval { require bytes } and bytes->import; }
  103         19755  
60              
61 462         938 foreach (grep { length } @$chunks) {
  461         1213  
62 461         741 $self->[TOTAL_OCTETS_LEFT] += length;
63 461         468 push @{$self->[OUTPUT_QUEUE]}, $_;
  461         1504  
64             }
65              
66 462 100 100     3224 if ($self->[TOTAL_OCTETS_LEFT] && (!$old_queue_octets)) {
67 416         949 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
68 416         1310 $self->[CURRENT_OCTETS_DONE] = 0;
69             }
70              
71 462         1264 $self->[TOTAL_OCTETS_LEFT];
72             }
73              
74             #------------------------------------------------------------------------------
75              
76             sub get {
77 2584     2584 1 7936 my ($self, $handle) = @_;
78              
79 2584         22887 my $result = sysread($handle, my $buffer = '', $self->[BLOCK_SIZE]);
80              
81             # sysread() returned a positive number of octets. Return whatever
82             # was read.
83 2584 100       10532 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 885 100       2073 if (defined $result) {
104 821         1756 $! = 0;
105 821         4248 return undef;
106             }
107              
108             # Nonfatal sysread() error. Return an empty list.
109 64 100 66     349 return [ ] if $! == EAGAIN or $! == EWOULDBLOCK;
110              
111             # fatal sysread error
112 13         53 undef;
113             }
114              
115             #------------------------------------------------------------------------------
116              
117             sub flush {
118 383     383 1 1255 my ($self, $handle) = @_;
119              
120             # Need to check lengths in octets, not characters.
121 103 50   103   21195 BEGIN { eval { require bytes } and bytes->import; }
  103         988  
122              
123             # Reset errno in case there is nothing to write.
124             # https://rt.cpan.org/Public/Bug/Display.html?id=87721
125 383         651 $! = 0;
126              
127             # syswrite() it, like we're supposed to
128 383         418 while (@{$self->[OUTPUT_QUEUE]}) {
  800         1833  
129 435         13256 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       1101 $! = 0 if defined $wrote_count;
138              
139 435 100       889 unless ($wrote_count) {
140 18 100 66     82 $! = 0 if $! == EAGAIN or $! == EWOULDBLOCK;
141 18         17 last;
142             }
143              
144 417         568 $self->[CURRENT_OCTETS_DONE] += $wrote_count;
145 417         560 $self->[TOTAL_OCTETS_LEFT] -= $wrote_count;
146 417 100       956 unless ($self->[CURRENT_OCTETS_LEFT] -= $wrote_count) {
147 400         358 shift(@{$self->[OUTPUT_QUEUE]});
  400         638  
148 400 100       656 if (@{$self->[OUTPUT_QUEUE]}) {
  400         905  
149 36         46 $self->[CURRENT_OCTETS_DONE] = 0;
150 36         65 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
151             }
152             else {
153 364         634 $self->[CURRENT_OCTETS_DONE] = $self->[CURRENT_OCTETS_LEFT] = 0;
154             }
155             }
156             }
157              
158 383         983 $self->[TOTAL_OCTETS_LEFT];
159             }
160              
161             #------------------------------------------------------------------------------
162              
163             sub get_out_messages_buffered {
164 44     44 1 1201 scalar(@{$_[0]->[OUTPUT_QUEUE]});
  44         1024  
165             }
166              
167             1;
168              
169             __END__