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   475 use strict;
  7         29  
  7         324  
10 7     7   39 use warnings::register;
  7         18  
  7         12192  
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 779 my $self = shift;
24 22   33     150 my $type = ref($self) || $self;
25              
26 22         136 my $vec = bless [undef,0], $type;
27              
28 22 100       144 $vec->add(@_)
29             if @_;
30              
31 22         75 $vec;
32             }
33              
34             sub add
35             {
36 27     27 1 795 shift->_update('add', @_);
37             }
38              
39              
40             sub remove
41             {
42 6     6 1 939 shift->_update('remove', @_);
43             }
44              
45              
46             sub exists
47             {
48 5     5 1 659 my $vec = shift;
49 5         15 my $fno = $vec->_fileno(shift);
50 5 50       10 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       87 return unless defined $f;
59 53 100       127 $f = $f->[0] if ref($f) eq 'ARRAY';
60 53 100       453 if($f =~ /^[0-9]+$/) { # plain file number
    100          
61 20         33 return $f;
62             }
63             elsif(defined(my $fd = fileno($f))) {
64 32         85 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         7 foreach my $i ( FIRST_FD .. $#$self ) {
71 4 100 100     13 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   48 my $vec = shift;
80 33         72 my $add = shift eq 'add';
81              
82 33         80 my $bits = $vec->[VEC_BITS];
83 33 100       99 $bits = '' unless defined $bits;
84              
85 33         41 my $count = 0;
86 33         55 my $f;
87 33         97 foreach $f (@_)
88             {
89 48         153 my $fn = $vec->_fileno($f);
90 48 100       78 if ($add) {
91 33 50       71 next unless defined $fn;
92 33         54 my $i = $fn + FIRST_FD;
93 33 100       86 if (defined $vec->[$i]) {
94 1         3 $vec->[$i] = $f; # if array rest might be different, so we update
95 1         2 next;
96             }
97 32         43 $vec->[FD_COUNT]++;
98 32         120 vec($bits, $fn, 1) = 1;
99 32         88 $vec->[$i] = $f;
100             } else { # remove
101 15 50       40 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         22 my $i = $fn + FIRST_FD;
115 15 100       25 next unless defined $vec->[$i];
116 12         15 $vec->[FD_COUNT]--;
117 12         24 vec($bits, $fn, 1) = 0;
118 12         20 $vec->[$i] = undef;
119             }
120             }
121 44         83 $count++;
122             }
123 33 100       79 $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef;
124 33         91 $count;
125             }
126              
127             sub can_read
128             {
129 19     19 1 189 my $vec = shift;
130 19         31 my $timeout = shift;
131 19         62 my $r = $vec->[VEC_BITS];
132              
133 19 100 100     24024968 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         2 my $timeout = shift;
142 1         2 my $w = $vec->[VEC_BITS];
143              
144 1 50 33     32 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         4 my $e = $vec->[VEC_BITS];
154              
155 2 50 33     12 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 678 warnings::warn("Call to deprecated method 'has_error', use 'has_exception'")
163             if warnings::enabled();
164 2         16 goto &has_exception;
165             }
166              
167             sub count
168             {
169 9     9 1 268 my $vec = shift;
170 9         19 $vec->[FD_COUNT];
171             }
172              
173             sub bits
174             {
175 6     6 1 135 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   7 my($a,$b,$c) = @_;
198 2 0       8 $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 17 if defined $_[0] && !ref($_[0]);
211              
212 2         6 my($r,$w,$e,$t) = @_;
213 2         5 my @result = ();
214              
215 2 50       6 my $rb = defined $r ? $r->[VEC_BITS] : undef;
216 2 50       10 my $wb = defined $w ? $w->[VEC_BITS] : undef;
217 2 100       6 my $eb = defined $e ? $e->[VEC_BITS] : undef;
218              
219 2 50       24 if(select($rb,$wb,$eb,$t) > 0)
220             {
221 2         6 my @r = ();
222 2         5 my @w = ();
223 2         4 my @e = ();
224 2 50       34 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         9 for( ; $i >= FIRST_FD ; $i--)
229             {
230 7         9 my $j = $i - FIRST_FD;
231 7 0 33     14 push(@r, $r->[$i])
      33        
232             if defined $rb && defined $r->[$i] && vec($rb, $j, 1);
233 7 100 66     35 push(@w, $w->[$i])
      66        
234             if defined $wb && defined $w->[$i] && vec($wb, $j, 1);
235 7 50 100     29 push(@e, $e->[$i])
      66        
236             if defined $eb && defined $e->[$i] && vec($eb, $j, 1);
237             }
238              
239 2         18 @result = (\@r, \@w, \@e);
240             }
241 2         11 @result;
242             }
243              
244              
245             sub handles
246             {
247 20     20 1 388 my $vec = shift;
248 20         42 my $bits = shift;
249 20         58 my @h = ();
250 20         29 my $i;
251 20         61 my $max = scalar(@$vec) - 1;
252              
253 20         70 for ($i = FIRST_FD; $i <= $max; $i++)
254             {
255 99 100       233 next unless defined $vec->[$i];
256 29 50 66     185 push(@h, $vec->[$i])
257             if !defined($bits) || vec($bits, $i - FIRST_FD, 1);
258             }
259            
260 20         313 @h;
261             }
262              
263             1;
264             __END__