From 1425eea04dd872dc6313f5315f317b2de288037c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Mon, 1 Jun 2015 14:15:30 +0000 Subject: IO-Async-0.67 --- lib/IO/Async/Loop/Select.pm | 294 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 294 insertions(+) create mode 100644 lib/IO/Async/Loop/Select.pm (limited to 'lib/IO/Async/Loop/Select.pm') diff --git a/lib/IO/Async/Loop/Select.pm b/lib/IO/Async/Loop/Select.pm new file mode 100644 index 0000000..0c3bd9c --- /dev/null +++ b/lib/IO/Async/Loop/Select.pm @@ -0,0 +1,294 @@ +# You may distribute under the terms of either the GNU General Public License +# or the Artistic License (the same terms as Perl itself) +# +# (C) Paul Evans, 2007-2015 -- leonerd@leonerd.org.uk + +package IO::Async::Loop::Select; + +use strict; +use warnings; + +our $VERSION = '0.67'; +use constant API_VERSION => '0.49'; + +use base qw( IO::Async::Loop ); + +use IO::Async::OS; + +use Carp; + +# select() on most platforms claims that ISREG files are always read- and +# write-ready, but not on MSWin32. We need to fake this +use constant FAKE_ISREG_READY => IO::Async::OS->HAVE_FAKE_ISREG_READY; +# select() on most platforms indicates write-ready when connect() fails, but +# not on MSWin32. Have to pull from evec in that case +use constant SELECT_CONNECT_EVEC => IO::Async::OS->HAVE_SELECT_CONNECT_EVEC; + +use constant _CAN_WATCHDOG => 1; +use constant WATCHDOG_ENABLE => IO::Async::Loop->WATCHDOG_ENABLE; + +=head1 NAME + +C - use C with C + +=head1 SYNOPSIS + +Normally an instance of this class would not be directly constructed by a +program. It may however, be useful for runinng L with an existing +program already using a C-based event loop, a pair of methods +C and C can be called immediately before and +after a C call, setting the bits +that the Loop is interested in. It will also adjust the C<$timeout> value if +appropriate, reducing it if the next event timeout the Loop requires is sooner +than the current value. + +=over 8 + +=item \$readvec + +=item \$writevec + +=item \$exceptvec + +Scalar references to the reading, writing and exception bitvectors + +=item \$timeout + +Scalar reference to the timeout value + +=back + +=cut + +sub pre_select +{ + my $self = shift; + my ( $readref, $writeref, $exceptref, $timeref ) = @_; + + # BITWISE operations + $$readref |= $self->{rvec}; + $$writeref |= $self->{wvec}; + $$exceptref |= $self->{evec}; + + $self->_adjust_timeout( $timeref ); + + $$timeref = 0 if FAKE_ISREG_READY and length $self->{avec}; + + # Round up to nearest millisecond + if( $$timeref ) { + my $mils = $$timeref * 1000; + my $fraction = $mils - int $mils; + $$timeref += ( 1 - $fraction ) / 1000 if $fraction; + } + + return; +} + +=head2 $loop->post_select( $readvec, $writevec, $exceptvec ) + +This method checks the returned bitvectors from a C syscall, performs it, then calls C to process the +result. It returns the total number of callbacks invoked by the +C method, or C if the underlying C syscall +returned an error. + +=cut + +sub loop_once +{ + my $self = shift; + my ( $timeout ) = @_; + + my ( $rvec, $wvec, $evec ) = ('') x 3; + + $self->pre_select( \$rvec, \$wvec, \$evec, \$timeout ); + + my $ret = select( $rvec, $wvec, $evec, $timeout ); + + if( $ret < 0 ) { + # r/w/e vec can't be trusted + $rvec = $wvec = $evec = ''; + } + + { + local $!; + $self->post_select( $rvec, $wvec, $evec ); + } + + return $ret; +} + +sub watch_io +{ + my $self = shift; + my %params = @_; + + $self->__watch_io( %params ); + + my $fileno = $params{handle}->fileno; + + vec( $self->{rvec}, $fileno, 1 ) = 1 if $params{on_read_ready}; + vec( $self->{wvec}, $fileno, 1 ) = 1 if $params{on_write_ready}; + + # MSWin32 does not indicate writeready for connect() errors, HUPs, etc + # but it does indicate exceptional + vec( $self->{evec}, $fileno, 1 ) = 1 if SELECT_CONNECT_EVEC and $params{on_write_ready}; + + vec( $self->{avec}, $fileno, 1 ) = 1 if FAKE_ISREG_READY and stat( $params{handle} ) and -f _; +} + +sub unwatch_io +{ + my $self = shift; + my %params = @_; + + $self->__unwatch_io( %params ); + + my $fileno = $params{handle}->fileno; + + vec( $self->{rvec}, $fileno, 1 ) = 0 if $params{on_read_ready}; + vec( $self->{wvec}, $fileno, 1 ) = 0 if $params{on_write_ready}; + + vec( $self->{evec}, $fileno, 1 ) = 0 if SELECT_CONNECT_EVEC and $params{on_write_ready}; + + vec( $self->{avec}, $fileno, 1 ) = 0 if FAKE_ISREG_READY and stat( $params{handle} ) and -f _; + + # vec will grow a bit vector as needed, but never shrink it. We'll trim + # trailing null bytes + $_ =~s/\0+\z// for $self->{rvec}, $self->{wvec}, $self->{evec}, $self->{avec}; +} + +=head1 SEE ALSO + +=over 4 + +=item * + +L - OO interface to select system call + +=back + +=head1 AUTHOR + +Paul Evans + +=cut + +0x55AA; -- cgit v1.2.1