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 105     105   1119 use strict;
  105         179  
  105         3438  
8              
9 105     105   359 use vars qw($VERSION);
  105         130  
  105         4706  
10             $VERSION = '1.370'; # NOTE - Should be #.### (three decimal places)
11              
12 105     105   411 use Errno qw(EAGAIN EWOULDBLOCK);
  105         132  
  105         4777  
13 105     105   397 use Carp qw(croak);
  105         236  
  105         31520  
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 950     950 1 157924 my $type = shift;
25 950         3458 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 950 100       2137 if (@_) {
34 16 100       39 if (@_ % 2) {
35 1         79 croak "$type requires an even number of parameters, if any";
36             }
37 15         36 my %args = @_;
38 15 100       37 if (defined $args{BlockSize}) {
39 14         42 $self->[BLOCK_SIZE] = delete $args{BlockSize};
40 14 100       200 croak "$type BlockSize must be greater than 0"
41             if ($self->[BLOCK_SIZE] <= 0);
42             }
43 14 100       51 if (keys %args) {
44 1         4 my @bad_args = sort keys %args;
45 1         92 croak "$type has unknown parameter(s): @bad_args";
46             }
47             }
48              
49 947         2722 $self;
50             }
51              
52             #------------------------------------------------------------------------------
53              
54             sub put {
55 474     474 1 1489 my ($self, $chunks) = @_;
56 474         845 my $old_queue_octets = $self->[TOTAL_OCTETS_LEFT];
57              
58             # Need to check lengths in octets, not characters.
59 105 50   105   295 BEGIN { eval { require bytes } and bytes->import; }
  105         13909  
60              
61 474         1160 foreach (grep { length } @$chunks) {
  473         1486  
62 473         853 $self->[TOTAL_OCTETS_LEFT] += length;
63 473         662 push @{$self->[OUTPUT_QUEUE]}, $_;
  473         1312  
64             }
65              
66 474 100 100     3537 if ($self->[TOTAL_OCTETS_LEFT] && (!$old_queue_octets)) {
67 427         1315 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
68 427         631 $self->[CURRENT_OCTETS_DONE] = 0;
69             }
70              
71 474         1312 $self->[TOTAL_OCTETS_LEFT];
72             }
73              
74             #------------------------------------------------------------------------------
75              
76             sub get {
77 2376     2376 1 8072 my ($self, $handle) = @_;
78              
79 2376         24817 my $result = sysread($handle, my $buffer = '', $self->[BLOCK_SIZE]);
80              
81             # sysread() returned a positive number of octets. Return whatever
82             # was read.
83 2376 100       8066 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 778 100       1690 if (defined $result) {
104 714         1618 $! = 0;
105 714         3123 return undef;
106             }
107              
108             # Nonfatal sysread() error. Return an empty list.
109 64 100 66     378 return [ ] if $! == EAGAIN or $! == EWOULDBLOCK;
110              
111             # fatal sysread error
112 13         63 undef;
113             }
114              
115             #------------------------------------------------------------------------------
116              
117             sub flush {
118 383     383 1 1832 my ($self, $handle) = @_;
119              
120             # Need to check lengths in octets, not characters.
121 105 50   105   38696 BEGIN { eval { require bytes } and bytes->import; }
  105         915  
122              
123             # Reset errno in case there is nothing to write.
124             # https://rt.cpan.org/Public/Bug/Display.html?id=87721
125 383         855 $! = 0;
126              
127             # syswrite() it, like we're supposed to
128 383         587 while (@{$self->[OUTPUT_QUEUE]}) {
  800         1556  
129 435         11148 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       1388 $! = 0 if defined $wrote_count;
138              
139 435 100       782 unless ($wrote_count) {
140 18 100 66     57 $! = 0 if $! == EAGAIN or $! == EWOULDBLOCK;
141 18         23 last;
142             }
143              
144 417         594 $self->[CURRENT_OCTETS_DONE] += $wrote_count;
145 417         561 $self->[TOTAL_OCTETS_LEFT] -= $wrote_count;
146 417 100       782 unless ($self->[CURRENT_OCTETS_LEFT] -= $wrote_count) {
147 400         486 shift(@{$self->[OUTPUT_QUEUE]});
  400         797  
148 400 100       1948 if (@{$self->[OUTPUT_QUEUE]}) {
  400         795  
149 36         48 $self->[CURRENT_OCTETS_DONE] = 0;
150 36         57 $self->[CURRENT_OCTETS_LEFT] = length($self->[OUTPUT_QUEUE]->[0]);
151             }
152             else {
153 364         747 $self->[CURRENT_OCTETS_DONE] = $self->[CURRENT_OCTETS_LEFT] = 0;
154             }
155             }
156             }
157              
158 383         1104 $self->[TOTAL_OCTETS_LEFT];
159             }
160              
161             #------------------------------------------------------------------------------
162              
163             sub get_out_messages_buffered {
164 44     44 1 891 scalar(@{$_[0]->[OUTPUT_QUEUE]});
  44         782  
165             }
166              
167             1;
168              
169             __END__