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   405 use strict;
  7         46  
  7         358  
10 7     7   60 use warnings::register;
  7         29  
  7         12264  
11             require Exporter;
12              
13             our $VERSION = "1.51";
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 142 my $self = shift;
24 22   33     111 my $type = ref($self) || $self;
25              
26 22         144 my $vec = bless [undef,0], $type;
27              
28 22 100       125 $vec->add(@_)
29             if @_;
30              
31 22         65 $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 114 shift->_update('remove', @_);
43             }
44              
45              
46             sub exists
47             {
48 5     5 1 58 my $vec = shift;
49 5         7 my $fno = $vec->_fileno(shift);
50 5 50       15 return undef unless defined $fno;
51 5         11 $vec->[$fno + FIRST_FD];
52             }
53              
54              
55             sub _fileno
56             {
57 53     53   97 my($self, $f) = @_;
58 53 50       80 return unless defined $f;
59 53 100       110 $f = $f->[0] if ref($f) eq 'ARRAY';
60 53 100       424 if($f =~ /^[0-9]+$/) { # plain file number
    100          
61 20         28 return $f;
62             }
63             elsif(defined(my $fd = fileno($f))) {
64 32         105 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         4 foreach my $i ( FIRST_FD .. $#$self ) {
71 4 100 100     15 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   66 my $vec = shift;
80 33         105 my $add = shift eq 'add';
81              
82 33         86 my $bits = $vec->[VEC_BITS];
83 33 100       75 $bits = '' unless defined $bits;
84              
85 33         41 my $count = 0;
86 33         36 my $f;
87 33         88 foreach $f (@_)
88             {
89 48         109 my $fn = $vec->_fileno($f);
90 48 100       92 if ($add) {
91 33 50       61 next unless defined $fn;
92 33         58 my $i = $fn + FIRST_FD;
93 33 100       65 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         33 $vec->[FD_COUNT]++;
98 32         106 vec($bits, $fn, 1) = 1;
99 32         87 $vec->[$i] = $f;
100             } else { # remove
101 15 50       32 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         16 my $i = $fn + FIRST_FD;
115 15 100       27 next unless defined $vec->[$i];
116 12         11 $vec->[FD_COUNT]--;
117 12         21 vec($bits, $fn, 1) = 0;
118 12         20 $vec->[$i] = undef;
119             }
120             }
121 44         73 $count++;
122             }
123 33 100       72 $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef;
124 33         68 $count;
125             }
126              
127             sub can_read
128             {
129 19     19 1 44 my $vec = shift;
130 19         27 my $timeout = shift;
131 19         40 my $r = $vec->[VEC_BITS];
132              
133 19 100 100     24029822 defined($r) && (select($r,undef,undef,$timeout) > 0)
134             ? handles($vec, $r)
135             : ();
136             }
137              
138             sub can_write
139             {
140 1     1 1 5 my $vec = shift;
141 1         7 my $timeout = shift;
142 1         3 my $w = $vec->[VEC_BITS];
143              
144 1 50 33     23 defined($w) && (select(undef,$w,undef,$timeout) > 0)
145             ? handles($vec, $w)
146             : ();
147             }
148              
149             sub has_exception
150             {
151 2     2 1 3 my $vec = shift;
152 2         3 my $timeout = shift;
153 2         3 my $e = $vec->[VEC_BITS];
154              
155 2 50 33     10 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 295 warnings::warn("Call to deprecated method 'has_error', use 'has_exception'")
163             if warnings::enabled();
164 2         14 goto &has_exception;
165             }
166              
167             sub count
168             {
169 9     9 1 42 my $vec = shift;
170 9         17 $vec->[FD_COUNT];
171             }
172              
173             sub bits
174             {
175 6     6 1 22 my $vec = shift;
176 6         11 $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   8 my($a,$b,$c) = @_;
198 2 0       22 $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         5 my($r,$w,$e,$t) = @_;
213 2         3 my @result = ();
214              
215 2 50       12 my $rb = defined $r ? $r->[VEC_BITS] : undef;
216 2 50       7 my $wb = defined $w ? $w->[VEC_BITS] : undef;
217 2 100       4 my $eb = defined $e ? $e->[VEC_BITS] : undef;
218              
219 2 50       25 if(select($rb,$wb,$eb,$t) > 0)
220             {
221 2         6 my @r = ();
222 2         3 my @w = ();
223 2         2 my @e = ();
224 2 50       22 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         6 for( ; $i >= FIRST_FD ; $i--)
229             {
230 7         9 my $j = $i - FIRST_FD;
231 7 0 33     15 push(@r, $r->[$i])
      33        
232             if defined $rb && defined $r->[$i] && vec($rb, $j, 1);
233 7 100 66     26 push(@w, $w->[$i])
      66        
234             if defined $wb && defined $w->[$i] && vec($wb, $j, 1);
235 7 50 100     26 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         9 @result;
242             }
243              
244              
245             sub handles
246             {
247 20     20 1 100 my $vec = shift;
248 20         35 my $bits = shift;
249 20         35 my @h = ();
250 20         45 my $i;
251 20         56 my $max = scalar(@$vec) - 1;
252              
253 20         52 for ($i = FIRST_FD; $i <= $max; $i++)
254             {
255 99 100       199 next unless defined $vec->[$i];
256 29 50 66     164 push(@h, $vec->[$i])
257             if !defined($bits) || vec($bits, $i - FIRST_FD, 1);
258             }
259            
260 20         622 @h;
261             }
262              
263             1;
264             __END__