File | /usr/local/lib/perl5/5.8.8/i686-linux/IO/Select.pm |
Statements Executed | 20759 |
Statement Execution Time | 48.0s |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
461 | 1 | 2 | 47.8s | 47.8s | CORE:sselect (opcode) | IO::Select::
461 | 1 | 1 | 69.3ms | 97.2ms | _update | IO::Select::
461 | 1 | 1 | 55.1ms | 55.1ms | handles | IO::Select::
461 | 1 | 1 | 29.0ms | 47.8s | can_write | IO::Select::
461 | 1 | 1 | 24.0ms | 133ms | new | IO::Select::
461 | 1 | 1 | 19.2ms | 27.9ms | _fileno | IO::Select::
461 | 1 | 1 | 11.8ms | 109ms | add | IO::Select::
461 | 1 | 2 | 8.70ms | 8.70ms | CORE:match (opcode) | IO::Select::
0 | 0 | 0 | 0s | 0s | BEGIN | IO::Select::
0 | 0 | 0 | 0s | 0s | _max | IO::Select::
0 | 0 | 0 | 0s | 0s | as_string | IO::Select::
0 | 0 | 0 | 0s | 0s | bits | IO::Select::
0 | 0 | 0 | 0s | 0s | can_read | IO::Select::
0 | 0 | 0 | 0s | 0s | count | IO::Select::
0 | 0 | 0 | 0s | 0s | exists | IO::Select::
0 | 0 | 0 | 0s | 0s | has_error | IO::Select::
0 | 0 | 0 | 0s | 0s | has_exception | IO::Select::
0 | 0 | 0 | 0s | 0s | remove | IO::Select::
0 | 0 | 0 | 0s | 0s | select | IO::Select::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # IO::Select.pm | ||||
2 | # | ||||
3 | # Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. 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 | 3 | 90µs | 1 | 25µs | use strict; # spent 25µs making 1 call to strict::import |
10 | 3 | 105µs | 1 | 704µs | use warnings::register; # spent 704µs making 1 call to warnings::register::import |
11 | 3 | 2.16ms | 1 | 214µs | use vars qw($VERSION @ISA); # spent 214µs making 1 call to vars::import |
12 | 1 | 7µs | require Exporter; | ||
13 | |||||
14 | 1 | 6µs | $VERSION = "1.17"; | ||
15 | |||||
16 | 1 | 11µs | @ISA = qw(Exporter); # This is only so we can do version checking | ||
17 | |||||
18 | sub VEC_BITS () {0} | ||||
19 | sub FD_COUNT () {1} | ||||
20 | sub FIRST_FD () {2} | ||||
21 | |||||
22 | sub new | ||||
23 | # spent 133ms (24.0+109) within IO::Select::new which was called 461 times, avg 289µs/call:
# 461 times (24.0ms+109ms) by IO::Socket::connect at line 118 of IO/Socket.pm, avg 289µs/call | ||||
24 | 2305 | 23.6ms | my $self = shift; | ||
25 | my $type = ref($self) || $self; | ||||
26 | |||||
27 | my $vec = bless [undef,0], $type; | ||||
28 | |||||
29 | $vec->add(@_) # spent 109ms making 461 calls to IO::Select::add, avg 236µs/call | ||||
30 | if @_; | ||||
31 | |||||
32 | $vec; | ||||
33 | } | ||||
34 | |||||
35 | sub add | ||||
36 | # spent 109ms (11.8+97.2) within IO::Select::add which was called 461 times, avg 236µs/call:
# 461 times (11.8ms+97.2ms) by IO::Select::new at line 29, avg 236µs/call | ||||
37 | 461 | 10.7ms | 461 | 97.2ms | shift->_update('add', @_); # spent 97.2ms making 461 calls to IO::Select::_update, avg 211µs/call |
38 | } | ||||
39 | |||||
40 | |||||
41 | sub remove | ||||
42 | { | ||||
43 | shift->_update('remove', @_); | ||||
44 | } | ||||
45 | |||||
46 | |||||
47 | sub exists | ||||
48 | { | ||||
49 | my $vec = shift; | ||||
50 | my $fno = $vec->_fileno(shift); | ||||
51 | return undef unless defined $fno; | ||||
52 | $vec->[$fno + FIRST_FD]; | ||||
53 | } | ||||
54 | |||||
55 | |||||
56 | sub _fileno | ||||
57 | # spent 27.9ms (19.2+8.70) within IO::Select::_fileno which was called 461 times, avg 60µs/call:
# 461 times (19.2ms+8.70ms) by IO::Select::_update at line 76, avg 60µs/call | ||||
58 | 1844 | 28.4ms | my($self, $f) = @_; | ||
59 | return unless defined $f; | ||||
60 | $f = $f->[0] if ref($f) eq 'ARRAY'; | ||||
61 | ($f =~ /^\d+$/) ? $f : fileno($f); # spent 8.70ms making 461 calls to IO::Select::CORE:match, avg 19µs/call | ||||
62 | } | ||||
63 | |||||
64 | sub _update | ||||
65 | # spent 97.2ms (69.3+27.9) within IO::Select::_update which was called 461 times, avg 211µs/call:
# 461 times (69.3ms+27.9ms) by IO::Select::add at line 37, avg 211µs/call | ||||
66 | 4149 | 37.0ms | my $vec = shift; | ||
67 | my $add = shift eq 'add'; | ||||
68 | |||||
69 | my $bits = $vec->[VEC_BITS]; | ||||
70 | $bits = '' unless defined $bits; | ||||
71 | |||||
72 | my $count = 0; | ||||
73 | my $f; | ||||
74 | foreach $f (@_) | ||||
75 | { | ||||
76 | 2305 | 21.8ms | 461 | 27.9ms | my $fn = $vec->_fileno($f); # spent 27.9ms making 461 calls to IO::Select::_fileno, avg 60µs/call |
77 | next unless defined $fn; | ||||
78 | my $i = $fn + FIRST_FD; | ||||
79 | 1844 | 11.3ms | if ($add) { | ||
80 | if (defined $vec->[$i]) { | ||||
81 | $vec->[$i] = $f; # if array rest might be different, so we update | ||||
82 | next; | ||||
83 | } | ||||
84 | $vec->[FD_COUNT]++; | ||||
85 | vec($bits, $fn, 1) = 1; | ||||
86 | $vec->[$i] = $f; | ||||
87 | } else { # remove | ||||
88 | next unless defined $vec->[$i]; | ||||
89 | $vec->[FD_COUNT]--; | ||||
90 | vec($bits, $fn, 1) = 0; | ||||
91 | $vec->[$i] = undef; | ||||
92 | } | ||||
93 | $count++; | ||||
94 | } | ||||
95 | $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef; | ||||
96 | $count; | ||||
97 | } | ||||
98 | |||||
99 | sub can_read | ||||
100 | { | ||||
101 | my $vec = shift; | ||||
102 | my $timeout = shift; | ||||
103 | my $r = $vec->[VEC_BITS]; | ||||
104 | |||||
105 | defined($r) && (select($r,undef,undef,$timeout) > 0) | ||||
106 | ? handles($vec, $r) | ||||
107 | : (); | ||||
108 | } | ||||
109 | |||||
110 | sub can_write | ||||
111 | # spent 47.8s (29.0ms+47.8) within IO::Select::can_write which was called 461 times, avg 104ms/call:
# 461 times (29.0ms+47.8s) by IO::Socket::connect at line 120 of IO/Socket.pm, avg 104ms/call | ||||
112 | 1844 | 47.8s | my $vec = shift; | ||
113 | my $timeout = shift; | ||||
114 | my $w = $vec->[VEC_BITS]; | ||||
115 | |||||
116 | defined($w) && (select(undef,$w,undef,$timeout) > 0) # spent 47.8s making 461 calls to IO::Select::CORE:sselect, avg 104ms/call
# spent 55.1ms making 461 calls to IO::Select::handles, avg 120µs/call | ||||
117 | ? handles($vec, $w) | ||||
118 | : (); | ||||
119 | } | ||||
120 | |||||
121 | sub has_exception | ||||
122 | { | ||||
123 | my $vec = shift; | ||||
124 | my $timeout = shift; | ||||
125 | my $e = $vec->[VEC_BITS]; | ||||
126 | |||||
127 | defined($e) && (select(undef,undef,$e,$timeout) > 0) | ||||
128 | ? handles($vec, $e) | ||||
129 | : (); | ||||
130 | } | ||||
131 | |||||
132 | sub has_error | ||||
133 | { | ||||
134 | warnings::warn("Call to deprecated method 'has_error', use 'has_exception'") | ||||
135 | if warnings::enabled(); | ||||
136 | goto &has_exception; | ||||
137 | } | ||||
138 | |||||
139 | sub count | ||||
140 | { | ||||
141 | my $vec = shift; | ||||
142 | $vec->[FD_COUNT]; | ||||
143 | } | ||||
144 | |||||
145 | sub bits | ||||
146 | { | ||||
147 | my $vec = shift; | ||||
148 | $vec->[VEC_BITS]; | ||||
149 | } | ||||
150 | |||||
151 | sub as_string # for debugging | ||||
152 | { | ||||
153 | my $vec = shift; | ||||
154 | my $str = ref($vec) . ": "; | ||||
155 | my $bits = $vec->bits; | ||||
156 | my $count = $vec->count; | ||||
157 | $str .= defined($bits) ? unpack("b*", $bits) : "undef"; | ||||
158 | $str .= " $count"; | ||||
159 | my @handles = @$vec; | ||||
160 | splice(@handles, 0, FIRST_FD); | ||||
161 | for (@handles) { | ||||
162 | $str .= " " . (defined($_) ? "$_" : "-"); | ||||
163 | } | ||||
164 | $str; | ||||
165 | } | ||||
166 | |||||
167 | sub _max | ||||
168 | { | ||||
169 | my($a,$b,$c) = @_; | ||||
170 | $a > $b | ||||
171 | ? $a > $c | ||||
172 | ? $a | ||||
173 | : $c | ||||
174 | : $b > $c | ||||
175 | ? $b | ||||
176 | : $c; | ||||
177 | } | ||||
178 | |||||
179 | sub select | ||||
180 | { | ||||
181 | shift | ||||
182 | if defined $_[0] && !ref($_[0]); | ||||
183 | |||||
184 | my($r,$w,$e,$t) = @_; | ||||
185 | my @result = (); | ||||
186 | |||||
187 | my $rb = defined $r ? $r->[VEC_BITS] : undef; | ||||
188 | my $wb = defined $w ? $w->[VEC_BITS] : undef; | ||||
189 | my $eb = defined $e ? $e->[VEC_BITS] : undef; | ||||
190 | |||||
191 | if(select($rb,$wb,$eb,$t) > 0) | ||||
192 | { | ||||
193 | my @r = (); | ||||
194 | my @w = (); | ||||
195 | my @e = (); | ||||
196 | my $i = _max(defined $r ? scalar(@$r)-1 : 0, | ||||
197 | defined $w ? scalar(@$w)-1 : 0, | ||||
198 | defined $e ? scalar(@$e)-1 : 0); | ||||
199 | |||||
200 | for( ; $i >= FIRST_FD ; $i--) | ||||
201 | { | ||||
202 | my $j = $i - FIRST_FD; | ||||
203 | push(@r, $r->[$i]) | ||||
204 | if defined $rb && defined $r->[$i] && vec($rb, $j, 1); | ||||
205 | push(@w, $w->[$i]) | ||||
206 | if defined $wb && defined $w->[$i] && vec($wb, $j, 1); | ||||
207 | push(@e, $e->[$i]) | ||||
208 | if defined $eb && defined $e->[$i] && vec($eb, $j, 1); | ||||
209 | } | ||||
210 | |||||
211 | @result = (\@r, \@w, \@e); | ||||
212 | } | ||||
213 | @result; | ||||
214 | } | ||||
215 | |||||
216 | |||||
217 | sub handles | ||||
218 | # spent 55.1ms within IO::Select::handles which was called 461 times, avg 120µs/call:
# 461 times (55.1ms+0s) by IO::Select::can_write at line 116, avg 120µs/call | ||||
219 | 3688 | 27.7ms | my $vec = shift; | ||
220 | my $bits = shift; | ||||
221 | my @h = (); | ||||
222 | my $i; | ||||
223 | my $max = scalar(@$vec) - 1; | ||||
224 | |||||
225 | 2305 | 14.3ms | for ($i = FIRST_FD; $i <= $max; $i++) | ||
226 | { | ||||
227 | 1 | 11.8ms | next unless defined $vec->[$i]; | ||
228 | push(@h, $vec->[$i]) | ||||
229 | if !defined($bits) || vec($bits, $i - FIRST_FD, 1); | ||||
230 | } | ||||
231 | |||||
232 | @h; | ||||
233 | } | ||||
234 | |||||
235 | 1 | 15µs | 1; | ||
236 | __END__ | ||||
237 | |||||
238 | =head1 NAME | ||||
239 | |||||
240 | IO::Select - OO interface to the select system call | ||||
241 | |||||
242 | =head1 SYNOPSIS | ||||
243 | |||||
244 | use IO::Select; | ||||
245 | |||||
246 | $s = IO::Select->new(); | ||||
247 | |||||
248 | $s->add(\*STDIN); | ||||
249 | $s->add($some_handle); | ||||
250 | |||||
251 | @ready = $s->can_read($timeout); | ||||
252 | |||||
253 | @ready = IO::Select->new(@handles)->can_read(0); | ||||
254 | |||||
255 | =head1 DESCRIPTION | ||||
256 | |||||
257 | The C<IO::Select> package implements an object approach to the system C<select> | ||||
258 | function call. It allows the user to see what IO handles, see L<IO::Handle>, | ||||
259 | are ready for reading, writing or have an exception pending. | ||||
260 | |||||
261 | =head1 CONSTRUCTOR | ||||
262 | |||||
263 | =over 4 | ||||
264 | |||||
265 | =item new ( [ HANDLES ] ) | ||||
266 | |||||
267 | The constructor creates a new object and optionally initialises it with a set | ||||
268 | of handles. | ||||
269 | |||||
270 | =back | ||||
271 | |||||
272 | =head1 METHODS | ||||
273 | |||||
274 | =over 4 | ||||
275 | |||||
276 | =item add ( HANDLES ) | ||||
277 | |||||
278 | Add the list of handles to the C<IO::Select> object. It is these values that | ||||
279 | will be returned when an event occurs. C<IO::Select> keeps these values in a | ||||
280 | cache which is indexed by the C<fileno> of the handle, so if more than one | ||||
281 | handle with the same C<fileno> is specified then only the last one is cached. | ||||
282 | |||||
283 | Each handle can be an C<IO::Handle> object, an integer or an array | ||||
284 | reference where the first element is an C<IO::Handle> or an integer. | ||||
285 | |||||
286 | =item remove ( HANDLES ) | ||||
287 | |||||
288 | Remove all the given handles from the object. This method also works | ||||
289 | by the C<fileno> of the handles. So the exact handles that were added | ||||
290 | need not be passed, just handles that have an equivalent C<fileno> | ||||
291 | |||||
292 | =item exists ( HANDLE ) | ||||
293 | |||||
294 | Returns a true value (actually the handle itself) if it is present. | ||||
295 | Returns undef otherwise. | ||||
296 | |||||
297 | =item handles | ||||
298 | |||||
299 | Return an array of all registered handles. | ||||
300 | |||||
301 | =item can_read ( [ TIMEOUT ] ) | ||||
302 | |||||
303 | Return an array of handles that are ready for reading. C<TIMEOUT> is | ||||
304 | the maximum amount of time to wait before returning an empty list, in | ||||
305 | seconds, possibly fractional. If C<TIMEOUT> is not given and any | ||||
306 | handles are registered then the call will block. | ||||
307 | |||||
308 | =item can_write ( [ TIMEOUT ] ) | ||||
309 | |||||
310 | Same as C<can_read> except check for handles that can be written to. | ||||
311 | |||||
312 | =item has_exception ( [ TIMEOUT ] ) | ||||
313 | |||||
314 | Same as C<can_read> except check for handles that have an exception | ||||
315 | condition, for example pending out-of-band data. | ||||
316 | |||||
317 | =item count () | ||||
318 | |||||
319 | Returns the number of handles that the object will check for when | ||||
320 | one of the C<can_> methods is called or the object is passed to | ||||
321 | the C<select> static method. | ||||
322 | |||||
323 | =item bits() | ||||
324 | |||||
325 | Return the bit string suitable as argument to the core select() call. | ||||
326 | |||||
327 | =item select ( READ, WRITE, EXCEPTION [, TIMEOUT ] ) | ||||
328 | |||||
329 | C<select> is a static method, that is you call it with the package name | ||||
330 | like C<new>. C<READ>, C<WRITE> and C<EXCEPTION> are either C<undef> or | ||||
331 | C<IO::Select> objects. C<TIMEOUT> is optional and has the same effect as | ||||
332 | for the core select call. | ||||
333 | |||||
334 | The result will be an array of 3 elements, each a reference to an array | ||||
335 | which will hold the handles that are ready for reading, writing and have | ||||
336 | exceptions respectively. Upon error an empty list is returned. | ||||
337 | |||||
338 | =back | ||||
339 | |||||
340 | =head1 EXAMPLE | ||||
341 | |||||
342 | Here is a short example which shows how C<IO::Select> could be used | ||||
343 | to write a server which communicates with several sockets while also | ||||
344 | listening for more connections on a listen socket | ||||
345 | |||||
346 | use IO::Select; | ||||
347 | use IO::Socket; | ||||
348 | |||||
349 | $lsn = new IO::Socket::INET(Listen => 1, LocalPort => 8080); | ||||
350 | $sel = new IO::Select( $lsn ); | ||||
351 | |||||
352 | while(@ready = $sel->can_read) { | ||||
353 | foreach $fh (@ready) { | ||||
354 | if($fh == $lsn) { | ||||
355 | # Create a new socket | ||||
356 | $new = $lsn->accept; | ||||
357 | $sel->add($new); | ||||
358 | } | ||||
359 | else { | ||||
360 | # Process socket | ||||
361 | |||||
362 | # Maybe we have finished with the socket | ||||
363 | $sel->remove($fh); | ||||
364 | $fh->close; | ||||
365 | } | ||||
366 | } | ||||
367 | } | ||||
368 | |||||
369 | =head1 AUTHOR | ||||
370 | |||||
371 | Graham Barr. Currently maintained by the Perl Porters. Please report all | ||||
372 | bugs to <perl5-porters@perl.org>. | ||||
373 | |||||
374 | =head1 COPYRIGHT | ||||
375 | |||||
376 | Copyright (c) 1997-8 Graham Barr <gbarr@pobox.com>. All rights reserved. | ||||
377 | This program is free software; you can redistribute it and/or | ||||
378 | modify it under the same terms as Perl itself. | ||||
379 | |||||
380 | =cut | ||||
381 | |||||
# spent 8.70ms within IO::Select::CORE:match which was called 461 times, avg 19µs/call:
# 461 times (8.70ms+0s) by IO::Select::_fileno at line 61 of IO/Select.pm, avg 19µs/call | |||||
# spent 47.8s within IO::Select::CORE:sselect which was called 461 times, avg 104ms/call:
# 461 times (47.8s+0s) by IO::Select::can_write at line 116 of IO/Select.pm, avg 104ms/call |