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