package IO::Select; use constant { HANDLES => 0, BITS => 1 }; sub new { my $package = shift; my $self = bless [ [], '' ], $package; $self->[HANDLES][fileno($_)] = $_ for @_; vec( $self->[BITS], fileno( $_ ), 1 ) = 1 for @_; return $self } sub add { my $self = shift; $self->[HANDLES][fileno($_)] = $_ for @_; vec( $self->[BITS], fileno( $_ ), 1 ) = 1 for @_; return $self; } sub remove { my $self = shift; for my $handle ( @_ ) { my( $bit ) = grep{ $self->[HANDLES][ $_ ] && $self->[HANDLES][ $_ ] == $handle } 0 .. $#{ $self->[HANDLES] }; warning( "Can't remove handle $handle; not found" ), next unless $bit; undef $self->[HANDLES][ $bit ]; vec( $self->[BITS], $bit, 1 ) = 0; } return $self; } sub _mapBitsToHandles { my( $self, $bits ) = @_; map{ vec( $bits, $_, 1 ) ? $self->[HANDLES][ $_ ] : () } 0 .. ( length( $bits ) * 8 -1 ); } sub can_read { my( $self, $timeout ) = @_; my $out = $self->[BITS]; select( $out, undef, undef, $timeout ); return $self->_mapBitsToHandles( $out ); } sub can_write { my( $self, $timeout ) = @_; my $out = $self->[BITS]; select( undef, $out, undef, $timeout ); return $self->_mapBitsToHandles( $out ); } sub has_exception { my( $self, $timeout ) = @_; my $out = $self->[BITS]; select( undef, undef, $out, $timeout ); return $self->_mapBitsToHandles( $out ); } sub count { my $self = shift; scalar $self->handles; } sub handles { my $self = shift; return grep defined(), @{ $self->[HANDLES] }; }