File Coverage

blib/lib/IO/Select.pm
Criterion Covered Total %
statement 98 119 82.3
branch 49 74 66.2
condition 23 42 54.7
subroutine 17 18 94.4
pod 11 13 84.6
total 198 266 74.4


line stmt bran cond sub pod time code
1             # IO::Select.pm
2             #
3             # Copyright (c) 1997-8 Graham Barr . All rights reserved.
4             # This program is free software; you can redistribute it and/or
5             # modify it under the same terms as Perl itself.
6              
7             package IO::Select;
8              
9 7     7   400 use strict;
  7         37  
  7         387  
10 7     7   39 use warnings::register;
  7         8  
  7         12496  
11             require Exporter;
12              
13             our $VERSION = "1.49";
14              
15             our @ISA = qw(Exporter); # This is only so we can do version checking
16              
17             sub VEC_BITS () {0}
18             sub FD_COUNT () {1}
19             sub FIRST_FD () {2}
20              
21             sub new
22             {
23 22     22 1 132 my $self = shift;
24 22   33     139 my $type = ref($self) || $self;
25              
26 22         119 my $vec = bless [undef,0], $type;
27              
28 22 100       121 $vec->add(@_)
29             if @_;
30              
31 22         69 $vec;
32             }
33              
34             sub add
35             {
36 27     27 1 178 shift->_update('add', @_);
37             }
38              
39              
40             sub remove
41             {
42 6     6 1 100 shift->_update('remove', @_);
43             }
44              
45              
46             sub exists
47             {
48 5     5 1 63 my $vec = shift;
49 5         7 my $fno = $vec->_fileno(shift);
50 5 50       9 return undef unless defined $fno;
51 5         17 $vec->[$fno + FIRST_FD];
52             }
53              
54              
55             sub _fileno
56             {
57 53     53   93 my($self, $f) = @_;
58 53 50       109 return unless defined $f;
59 53 100       123 $f = $f->[0] if ref($f) eq 'ARRAY';
60 53 100       440 if($f =~ /^[0-9]+$/) { # plain file number
    100          
61 20         33 return $f;
62             }
63             elsif(defined(my $fd = fileno($f))) {
64 32         81 return $fd;
65             }
66             else {
67             # Neither a plain file number nor an opened filehandle; but maybe it was
68             # previously registered and has since been closed. ->remove still wants to
69             # know what fileno it had
70 1         5 foreach my $i ( FIRST_FD .. $#$self ) {
71 4 100 100     14 return $i - FIRST_FD if defined $self->[$i] && $self->[$i] == $f;
72             }
73 0         0 return undef;
74             }
75             }
76              
77             sub _update
78             {
79 33     33   79 my $vec = shift;
80 33         148 my $add = shift eq 'add';
81              
82 33         101 my $bits = $vec->[VEC_BITS];
83 33 100       79 $bits = '' unless defined $bits;
84              
85 33         53 my $count = 0;
86 33         40 my $f;
87 33         98 foreach $f (@_)
88             {
89 48         157 my $fn = $vec->_fileno($f);
90 48 100       107 if ($add) {
91 33 50       70 next unless defined $fn;
92 33         49 my $i = $fn + FIRST_FD;
93 33 100       107 if (defined $vec->[$i]) {
94 1         2 $vec->[$i] = $f; # if array rest might be different, so we update
95 1         2 next;
96             }
97 32         40 $vec->[FD_COUNT]++;
98 32         112 vec($bits, $fn, 1) = 1;
99 32         102 $vec->[$i] = $f;
100             } else { # remove
101 15 50       30 if ( ! defined $fn ) { # remove if fileno undef'd
102 0         0 $fn = 0;
103 0         0 for my $fe (@{$vec}[FIRST_FD .. $#$vec]) {
  0         0  
104 0 0 0     0 if (defined($fe) && $fe == $f) {
105 0         0 $vec->[FD_COUNT]--;
106 0         0 $fe = undef;
107 0         0 vec($bits, $fn, 1) = 0;
108 0         0 last;
109             }
110 0         0 ++$fn;
111             }
112             }
113             else {
114 15         17 my $i = $fn + FIRST_FD;
115 15 100       25 next unless defined $vec->[$i];
116 12         12 $vec->[FD_COUNT]--;
117 12         20 vec($bits, $fn, 1) = 0;
118 12         19 $vec->[$i] = undef;
119             }
120             }
121 44         92 $count++;
122             }
123 33 100       105 $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef;
124 33         83 $count;
125             }
126              
127             sub can_read
128             {
129 19     19 1 48 my $vec = shift;
130 19         31 my $timeout = shift;
131 19         49 my $r = $vec->[VEC_BITS];
132              
133 19 100 100     24028014 defined($r) && (select($r,undef,undef,$timeout) > 0)
134             ? handles($vec, $r)
135             : ();
136             }
137              
138             sub can_write
139             {
140 1     1 1 4 my $vec = shift;
141 1         2 my $timeout = shift;
142 1         1 my $w = $vec->[VEC_BITS];
143              
144 1 50 33     31 defined($w) && (select(undef,$w,undef,$timeout) > 0)
145             ? handles($vec, $w)
146             : ();
147             }
148              
149             sub has_exception
150             {
151 2     2 1 4 my $vec = shift;
152 2         2 my $timeout = shift;
153 2         3 my $e = $vec->[VEC_BITS];
154              
155 2 50 33     8 defined($e) && (select(undef,undef,$e,$timeout) > 0)
156             ? handles($vec, $e)
157             : ();
158             }
159              
160             sub has_error
161             {
162 2 100   2 0 307 warnings::warn("Call to deprecated method 'has_error', use 'has_exception'")
163             if warnings::enabled();
164 2         13 goto &has_exception;
165             }
166              
167             sub count
168             {
169 9     9 1 41 my $vec = shift;
170 9         15 $vec->[FD_COUNT];
171             }
172              
173             sub bits
174             {
175 6     6 1 912 my $vec = shift;
176 6         13 $vec->[VEC_BITS];
177             }
178              
179             sub as_string # for debugging
180             {
181 0     0 0 0 my $vec = shift;
182 0         0 my $str = ref($vec) . ": ";
183 0         0 my $bits = $vec->bits;
184 0         0 my $count = $vec->count;
185 0 0       0 $str .= defined($bits) ? unpack("b*", $bits) : "undef";
186 0         0 $str .= " $count";
187 0         0 my @handles = @$vec;
188 0         0 splice(@handles, 0, FIRST_FD);
189 0         0 for (@handles) {
190 0 0       0 $str .= " " . (defined($_) ? "$_" : "-");
191             }
192 0         0 $str;
193             }
194              
195             sub _max
196             {
197 2     2   6 my($a,$b,$c) = @_;
198 2 0       9 $a > $b
    100          
    50          
199             ? $a > $c
200             ? $a
201             : $c
202             : $b > $c
203             ? $b
204             : $c;
205             }
206              
207             sub select
208             {
209             shift
210 2 50 33 2 1 10 if defined $_[0] && !ref($_[0]);
211              
212 2         6 my($r,$w,$e,$t) = @_;
213 2         4 my @result = ();
214              
215 2 50       11 my $rb = defined $r ? $r->[VEC_BITS] : undef;
216 2 50       7 my $wb = defined $w ? $w->[VEC_BITS] : undef;
217 2 100       5 my $eb = defined $e ? $e->[VEC_BITS] : undef;
218              
219 2 50       27 if(select($rb,$wb,$eb,$t) > 0)
220             {
221 2         5 my @r = ();
222 2         3 my @w = ();
223 2         3 my @e = ();
224 2 50       21 my $i = _max(defined $r ? scalar(@$r)-1 : 0,
    50          
    100          
225             defined $w ? scalar(@$w)-1 : 0,
226             defined $e ? scalar(@$e)-1 : 0);
227              
228 2         7 for( ; $i >= FIRST_FD ; $i--)
229             {
230 7         9 my $j = $i - FIRST_FD;
231 7 0 33     11 push(@r, $r->[$i])
      33        
232             if defined $rb && defined $r->[$i] && vec($rb, $j, 1);
233 7 100 66     27 push(@w, $w->[$i])
      66        
234             if defined $wb && defined $w->[$i] && vec($wb, $j, 1);
235 7 50 100     24 push(@e, $e->[$i])
      66        
236             if defined $eb && defined $e->[$i] && vec($eb, $j, 1);
237             }
238              
239 2         13 @result = (\@r, \@w, \@e);
240             }
241 2         10 @result;
242             }
243              
244              
245             sub handles
246             {
247 20     20 1 115 my $vec = shift;
248 20         43 my $bits = shift;
249 20         79 my @h = ();
250 20         33 my $i;
251 20         51 my $max = scalar(@$vec) - 1;
252              
253 20         72 for ($i = FIRST_FD; $i <= $max; $i++)
254             {
255 99 100       270 next unless defined $vec->[$i];
256 29 50 66     180 push(@h, $vec->[$i])
257             if !defined($bits) || vec($bits, $i - FIRST_FD, 1);
258             }
259            
260 20         271 @h;
261             }
262              
263             1;
264             __END__