| File | /usr/local/lib/perl5/5.10.1/darwin-2level/IO/Select.pm |
| Statements Executed | 103 |
| Statement Execution Time | 40.1ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 2 | 1 | 2 | 38.9ms | 38.9ms | IO::Select::CORE:sselect (opcode) |
| 2 | 1 | 1 | 56µs | 56µs | IO::Select::handles |
| 2 | 1 | 1 | 46µs | 39.0ms | IO::Select::can_write |
| 1 | 1 | 1 | 44µs | 56µs | IO::Select::BEGIN@9 |
| 2 | 1 | 1 | 34µs | 68µs | IO::Select::_update |
| 2 | 1 | 1 | 25µs | 34µs | IO::Select::_fileno |
| 2 | 1 | 1 | 24µs | 101µs | IO::Select::new |
| 1 | 1 | 1 | 16µs | 106µs | IO::Select::BEGIN@10 |
| 1 | 1 | 1 | 11µs | 57µs | IO::Select::BEGIN@11 |
| 2 | 1 | 1 | 10µs | 78µs | IO::Select::add |
| 2 | 1 | 2 | 9µs | 9µs | IO::Select::CORE:match (opcode) |
| 0 | 0 | 0 | 0s | 0s | IO::Select::_max |
| 0 | 0 | 0 | 0s | 0s | IO::Select::as_string |
| 0 | 0 | 0 | 0s | 0s | IO::Select::bits |
| 0 | 0 | 0 | 0s | 0s | IO::Select::can_read |
| 0 | 0 | 0 | 0s | 0s | IO::Select::count |
| 0 | 0 | 0 | 0s | 0s | IO::Select::exists |
| 0 | 0 | 0 | 0s | 0s | IO::Select::has_error |
| 0 | 0 | 0 | 0s | 0s | IO::Select::has_exception |
| 0 | 0 | 0 | 0s | 0s | IO::Select::remove |
| 0 | 0 | 0 | 0s | 0s | IO::Select::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 | 88µs | 2 | 69µs | # spent 56µs (44+13) within IO::Select::BEGIN@9 which was called
# once (44µs+13µs) by IO::Socket::connect at line 9 # spent 56µs making 1 call to IO::Select::BEGIN@9
# spent 13µs making 1 call to strict::import |
| 10 | 3 | 35µs | 2 | 195µs | # spent 106µs (16+89) within IO::Select::BEGIN@10 which was called
# once (16µs+89µs) by IO::Socket::connect at line 10 # spent 106µs making 1 call to IO::Select::BEGIN@10
# spent 90µs making 1 call to warnings::register::import |
| 11 | 3 | 827µs | 2 | 103µs | # spent 57µs (11+46) within IO::Select::BEGIN@11 which was called
# once (11µs+46µs) by IO::Socket::connect at line 11 # spent 57µs making 1 call to IO::Select::BEGIN@11
# spent 46µs making 1 call to vars::import |
| 12 | 1 | 800ns | require Exporter; | ||
| 13 | |||||
| 14 | 1 | 600ns | $VERSION = "1.17"; | ||
| 15 | |||||
| 16 | 1 | 8µ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 101µs (24+78) within IO::Select::new which was called 2 times, avg 51µs/call:
# 2 times (24µs+78µs) by IO::Socket::connect at line 118 of IO/Socket.pm, avg 51µs/call | ||||
| 24 | 2 | 1µs | my $self = shift; | ||
| 25 | 2 | 1µs | my $type = ref($self) || $self; | ||
| 26 | |||||
| 27 | 2 | 10µs | my $vec = bless [undef,0], $type; | ||
| 28 | |||||
| 29 | 2 | 4µs | 2 | 78µs | $vec->add(@_) # spent 78µs making 2 calls to IO::Select::add, avg 39µs/call |
| 30 | if @_; | ||||
| 31 | |||||
| 32 | 2 | 5µs | $vec; | ||
| 33 | } | ||||
| 34 | |||||
| 35 | sub add | ||||
| 36 | # spent 78µs (10+68) within IO::Select::add which was called 2 times, avg 39µs/call:
# 2 times (10µs+68µs) by IO::Select::new at line 29, avg 39µs/call | ||||
| 37 | 2 | 8µs | 2 | 68µs | shift->_update('add', @_); # spent 68µs making 2 calls to IO::Select::_update, avg 34µ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 34µs (25+9) within IO::Select::_fileno which was called 2 times, avg 17µs/call:
# 2 times (25µs+9µs) by IO::Select::_update at line 76, avg 17µs/call | ||||
| 58 | 2 | 2µs | my($self, $f) = @_; | ||
| 59 | 2 | 600ns | return unless defined $f; | ||
| 60 | 2 | 2µs | $f = $f->[0] if ref($f) eq 'ARRAY'; | ||
| 61 | 2 | 33µs | 2 | 9µs | ($f =~ /^\d+$/) ? $f : fileno($f); # spent 9µs making 2 calls to IO::Select::CORE:match, avg 4µs/call |
| 62 | } | ||||
| 63 | |||||
| 64 | sub _update | ||||
| 65 | # spent 68µs (34+34) within IO::Select::_update which was called 2 times, avg 34µs/call:
# 2 times (34µs+34µs) by IO::Select::add at line 37, avg 34µs/call | ||||
| 66 | 2 | 800ns | my $vec = shift; | ||
| 67 | 2 | 2µs | my $add = shift eq 'add'; | ||
| 68 | |||||
| 69 | 2 | 1µs | my $bits = $vec->[VEC_BITS]; | ||
| 70 | 2 | 1µs | $bits = '' unless defined $bits; | ||
| 71 | |||||
| 72 | 2 | 400ns | my $count = 0; | ||
| 73 | 2 | 300ns | my $f; | ||
| 74 | 2 | 2µs | foreach $f (@_) | ||
| 75 | { | ||||
| 76 | 2 | 4µs | 2 | 34µs | my $fn = $vec->_fileno($f); # spent 34µs making 2 calls to IO::Select::_fileno, avg 17µs/call |
| 77 | 2 | 200ns | next unless defined $fn; | ||
| 78 | 2 | 1µs | my $i = $fn + FIRST_FD; | ||
| 79 | 2 | 900ns | if ($add) { | ||
| 80 | 2 | 600ns | if (defined $vec->[$i]) { | ||
| 81 | $vec->[$i] = $f; # if array rest might be different, so we update | ||||
| 82 | next; | ||||
| 83 | } | ||||
| 84 | 2 | 500ns | $vec->[FD_COUNT]++; | ||
| 85 | 2 | 3µs | vec($bits, $fn, 1) = 1; | ||
| 86 | 2 | 2µs | $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 | 2 | 2µs | $count++; | ||
| 94 | } | ||||
| 95 | 2 | 1µs | $vec->[VEC_BITS] = $vec->[FD_COUNT] ? $bits : undef; | ||
| 96 | 2 | 6µs | $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 39.0ms (46µs+39.0) within IO::Select::can_write which was called 2 times, avg 19.5ms/call:
# 2 times (46µs+39.0ms) by IO::Socket::connect at line 121 of IO/Socket.pm, avg 19.5ms/call | ||||
| 112 | 2 | 600ns | my $vec = shift; | ||
| 113 | 2 | 600ns | my $timeout = shift; | ||
| 114 | 2 | 900ns | my $w = $vec->[VEC_BITS]; | ||
| 115 | |||||
| 116 | 2 | 39.0ms | 4 | 39.0ms | defined($w) && (select(undef,$w,undef,$timeout) > 0) # spent 38.9ms making 2 calls to IO::Select::CORE:sselect, avg 19.5ms/call
# spent 56µs making 2 calls to IO::Select::handles, avg 28µ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 56µs within IO::Select::handles which was called 2 times, avg 28µs/call:
# 2 times (56µs+0s) by IO::Select::can_write at line 116, avg 28µs/call | ||||
| 219 | 2 | 4µs | my $vec = shift; | ||
| 220 | 2 | 1µs | my $bits = shift; | ||
| 221 | 2 | 4µs | my @h = (); | ||
| 222 | 2 | 400ns | my $i; | ||
| 223 | 2 | 4µs | my $max = scalar(@$vec) - 1; | ||
| 224 | |||||
| 225 | 2 | 6µs | for ($i = FIRST_FD; $i <= $max; $i++) | ||
| 226 | { | ||||
| 227 | 8 | 6µs | next unless defined $vec->[$i]; | ||
| 228 | 2 | 6µs | push(@h, $vec->[$i]) | ||
| 229 | if !defined($bits) || vec($bits, $i - FIRST_FD, 1); | ||||
| 230 | 2 | 700ns | } | ||
| 231 | |||||
| 232 | 2 | 13µs | @h; | ||
| 233 | } | ||||
| 234 | |||||
| 235 | 1 | 6µ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 9µs within IO::Select::CORE:match which was called 2 times, avg 4µs/call:
# 2 times (9µs+0s) by IO::Select::_fileno at line 61 of IO/Select.pm, avg 4µs/call | |||||
# spent 38.9ms within IO::Select::CORE:sselect which was called 2 times, avg 19.5ms/call:
# 2 times (38.9ms+0s) by IO::Select::can_write at line 116 of IO/Select.pm, avg 19.5ms/call |