File Coverage

blib/lib/IO/Select.pm
Criterion Covered Total %
statement 98 119 82.3
branch 50 74 67.5
condition 24 42 57.1
subroutine 17 18 94.4
pod 11 13 84.6
total 200 266 75.1


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 9     9   922023 use strict;
  9         70  
  9         716  
10 9     9   134 use warnings::register;
  9         24  
  9         17674  
11             require Exporter;
12              
13             our $VERSION = "1.55";
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 50     50 1 575030 my $self = shift;
24 50   33     615 my $type = ref($self) || $self;
25              
26 50         343 my $vec = bless [undef,0], $type;
27              
28 50 100       470 $vec->add(@_)
29             if @_;
30              
31 50         5706 $vec;
32             }
33              
34             sub add
35             {
36 55     55 1 550 shift->_update('add', @_);
37             }
38              
39              
40             sub remove
41             {
42 61     61 1 359 shift->_update('remove', @_);
43             }
44              
45              
46             sub exists
47             {
48 5     5 1 67 my $vec = shift;
49 5         11 my $fno = $vec->_fileno(shift);
50 5 50       29 return undef unless defined $fno;
51 5         14 $vec->[$fno + FIRST_FD];
52             }
53              
54              
55             sub _fileno
56             {
57 163     163   400 my($self, $f) = @_;
58 163 50       436 return unless defined $f;
59 163 100       547 $f = $f->[0] if ref($f) eq 'ARRAY';
60 163 100       1531 if($f =~ /^[0-9]+$/) { # plain file number
    100          
61 20         46 return $f;
62             }
63             elsif(defined(my $fd = fileno($f))) {
64 141         378 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 2         10 foreach my $i ( FIRST_FD .. $#$self ) {
71 8 100 100     65 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 116     116   219 my $vec = shift;
80 116         331 my $add = shift eq 'add';
81              
82 116         315 my $bits = $vec->[VEC_BITS];
83 116 100       461 $bits = '' unless defined $bits;
84              
85 116         197 my $count = 0;
86 116         205 my $f;
87 116         443 foreach $f (@_)
88             {
89 158         549 my $fn = $vec->_fileno($f);
90 158 100       394 if ($add) {
91 88 50       225 next unless defined $fn;
92 88         156 my $i = $fn + FIRST_FD;
93 88 100       285 if (defined $vec->[$i]) {
94 1         4 $vec->[$i] = $f; # if array rest might be different, so we update
95 1         2 next;
96             }
97 87         135 $vec->[FD_COUNT]++;
98 87         458 vec($bits, $fn, 1) = 1;
99 87         302 $vec->[$i] = $f;
100             } else { # remove
101 70 50       231 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 70         128 my $i = $fn + FIRST_FD;
115 70 100       311 next unless defined $vec->[$i];
116 67         116 $vec->[FD_COUNT]--;
117 67         302 vec($bits, $fn, 1) = 0;
118 67         176 $vec->[$i] = undef;
119             }
120             }
121 154         352 $count++;
122             }
123 116 100       364 $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef;
124 116         474 $count;
125             }
126              
127             sub can_read
128             {
129 224     224 1 3484536 my $vec = shift;
130 224         457 my $timeout = shift;
131 224         585 my $r = $vec->[VEC_BITS];
132              
133 224 100 100     89837175 defined($r) && (select($r,undef,undef,$timeout) > 0)
134             ? handles($vec, $r)
135             : ();
136             }
137              
138             sub can_write
139             {
140 1     1 1 6 my $vec = shift;
141 1         2 my $timeout = shift;
142 1         3 my $w = $vec->[VEC_BITS];
143              
144 1 50 33     40 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         4 my $timeout = shift;
153 2         5 my $e = $vec->[VEC_BITS];
154              
155 2 50 33     11 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 510 warnings::warn("Call to deprecated method 'has_error', use 'has_exception'")
163             if warnings::enabled();
164 2         20 goto &has_exception;
165             }
166              
167             sub count
168             {
169 9     9 1 70 my $vec = shift;
170 9         24 $vec->[FD_COUNT];
171             }
172              
173             sub bits
174             {
175 6     6 1 44 my $vec = shift;
176 6         16 $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   4 my($a,$b,$c) = @_;
198 2 0       10 $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 28 if defined $_[0] && !ref($_[0]);
211              
212 2         7 my($r,$w,$e,$t) = @_;
213 2         4 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       5 my $eb = defined $e ? $e->[VEC_BITS] : undef;
218              
219 2 50       24 if(select($rb,$wb,$eb,$t) > 0)
220             {
221 2         5 my @r = ();
222 2         4 my @w = ();
223 2         3 my @e = ();
224 2 50       15 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         27 for( ; $i >= FIRST_FD ; $i--)
229             {
230 7         10 my $j = $i - FIRST_FD;
231 7 0 33     19 push(@r, $r->[$i])
      33        
232             if defined $rb && defined $r->[$i] && vec($rb, $j, 1);
233 7 100 66     57 push(@w, $w->[$i])
      66        
234             if defined $wb && defined $w->[$i] && vec($wb, $j, 1);
235 7 50 100     28 push(@e, $e->[$i])
      66        
236             if defined $eb && defined $e->[$i] && vec($eb, $j, 1);
237             }
238              
239 2         29 @result = (\@r, \@w, \@e);
240             }
241 2         11 @result;
242             }
243              
244              
245             sub handles
246             {
247 200     200 1 1031 my $vec = shift;
248 200         468 my $bits = shift;
249 200         438 my @h = ();
250 200         424 my $i;
251 200         584 my $max = scalar(@$vec) - 1;
252              
253 200         820 for ($i = FIRST_FD; $i <= $max; $i++)
254             {
255 1175 100       3231 next unless defined $vec->[$i];
256 384 100 100     12978 push(@h, $vec->[$i])
257             if !defined($bits) || vec($bits, $i - FIRST_FD, 1);
258             }
259            
260 200         19794 @h;
261             }
262              
263             1;
264             __END__