| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #  You may distribute under the terms of either the GNU General Public License | 
| 2 |  |  |  |  |  |  | #  or the Artistic License (the same terms as Perl itself) | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | #  (C) Paul Evans, 2007-2020 -- leonerd@leonerd.org.uk | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | package IO::Async::Loop::Poll; | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 85 |  |  | 85 |  | 2680 | use strict; | 
|  | 85 |  |  |  |  | 200 |  | 
|  | 85 |  |  |  |  | 2953 |  | 
| 9 | 85 |  |  | 85 |  | 489 | use warnings; | 
|  | 85 |  |  |  |  | 184 |  | 
|  | 85 |  |  |  |  | 4415 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | our $VERSION = '0.79'; | 
| 12 | 85 |  |  | 85 |  | 510 | use constant API_VERSION => '0.49'; | 
|  | 85 |  |  |  |  | 203 |  | 
|  | 85 |  |  |  |  | 7255 |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 85 |  |  | 85 |  | 1191 | use base qw( IO::Async::Loop ); | 
|  | 85 |  |  |  |  | 208 |  | 
|  | 85 |  |  |  |  | 18694 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 | 85 |  |  | 85 |  | 589 | use Carp; | 
|  | 85 |  |  |  |  | 216 |  | 
|  | 85 |  |  |  |  | 6153 |  | 
| 17 |  |  |  |  |  |  |  | 
| 18 | 85 |  |  | 85 |  | 45043 | use IO::Poll qw( POLLIN POLLOUT POLLPRI POLLHUP POLLERR ); | 
|  | 85 |  |  |  |  | 425931 |  | 
|  | 85 |  |  |  |  | 6709 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 85 |  |  | 85 |  | 1224 | use Errno qw( EINTR ); | 
|  | 85 |  |  |  |  | 1552 |  | 
|  | 85 |  |  |  |  | 8642 |  | 
| 21 | 85 |  |  | 85 |  | 553 | use Fcntl qw( S_ISREG ); | 
|  | 85 |  |  |  |  | 189 |  | 
|  | 85 |  |  |  |  | 5900 |  | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | # Only Linux, or FreeBSD 8.0 and above, are known always to be able to report | 
| 24 |  |  |  |  |  |  | # EOF conditions on filehandles using POLLHUP | 
| 25 |  |  |  |  |  |  | use constant _CAN_ON_HANGUP => | 
| 26 |  |  |  |  |  |  | ( $^O eq "linux" ) || | 
| 27 | 85 |  | 33 | 85 |  | 584 | ( $^O eq "freebsd" and do { no warnings 'numeric'; (POSIX::uname)[2] >= 8.0 } ); | 
|  | 85 |  |  | 85 |  | 176 |  | 
|  | 85 |  |  |  |  | 5877 |  | 
|  | 85 |  |  |  |  | 545 |  | 
|  | 85 |  |  |  |  | 195 |  | 
|  | 85 |  |  |  |  | 7116 |  | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | # poll() on most platforms claims that ISREG files are always read- and | 
| 30 |  |  |  |  |  |  | # write-ready, but not on MSWin32. We need to fake this | 
| 31 | 85 |  |  | 85 |  | 648 | use constant FAKE_ISREG_READY => IO::Async::OS->HAVE_FAKE_ISREG_READY; | 
|  | 85 |  |  |  |  | 210 |  | 
|  | 85 |  |  |  |  | 6777 |  | 
| 32 |  |  |  |  |  |  | # poll() on most platforms indicates POLLOUT when connect() fails, but not on | 
| 33 |  |  |  |  |  |  | # MSWin32. Have to poll also for POLLPRI in that case | 
| 34 | 85 |  |  | 85 |  | 564 | use constant POLL_CONNECT_POLLPRI => IO::Async::OS->HAVE_POLL_CONNECT_POLLPRI; | 
|  | 85 |  |  |  |  | 166 |  | 
|  | 85 |  |  |  |  | 5558 |  | 
| 35 |  |  |  |  |  |  |  | 
| 36 | 85 |  |  | 85 |  | 665 | use constant _CAN_WATCHDOG => 1; | 
|  | 85 |  |  |  |  | 210 |  | 
|  | 85 |  |  |  |  | 4883 |  | 
| 37 | 85 |  |  | 85 |  | 538 | use constant WATCHDOG_ENABLE => IO::Async::Loop->WATCHDOG_ENABLE; | 
|  | 85 |  |  |  |  | 225 |  | 
|  | 85 |  |  |  |  | 106922 |  | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | =head1 NAME | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | C - use C with C | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | Normally an instance of this class would not be directly constructed by a | 
| 46 |  |  |  |  |  |  | program. It may however, be useful for runinng L with an existing | 
| 47 |  |  |  |  |  |  | program already using an C object. | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | use IO::Poll; | 
| 50 |  |  |  |  |  |  | use IO::Async::Loop::Poll; | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | my $poll = IO::Poll->new; | 
| 53 |  |  |  |  |  |  | my $loop = IO::Async::Loop::Poll->new( poll => $poll ); | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | $loop->add( ... ); | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | while(1) { | 
| 58 |  |  |  |  |  |  | my $timeout = ... | 
| 59 |  |  |  |  |  |  | my $ret = $poll->poll( $timeout ); | 
| 60 |  |  |  |  |  |  | $loop->post_poll; | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | This subclass of L uses the C system call to perform | 
| 66 |  |  |  |  |  |  | read-ready and write-ready tests. | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | By default, this loop will use the underlying C system call directly, | 
| 69 |  |  |  |  |  |  | bypassing the usual L object wrapper around it because of a number | 
| 70 |  |  |  |  |  |  | of bugs and design flaws in that class; namely | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | =over 2 | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | =item * | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | L - IO::Poll relies on | 
| 77 |  |  |  |  |  |  | stable stringification of IO handles | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  | =item * | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | L - IO::Poll->poll() with no | 
| 82 |  |  |  |  |  |  | handles always returns immediately | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | =back | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | However, to integrate with existing code that uses an C object, a | 
| 87 |  |  |  |  |  |  | C can be called immediately after the C method that | 
| 88 |  |  |  |  |  |  | C object. The appropriate mask bits are maintained on the | 
| 89 |  |  |  |  |  |  | C object when notifiers are added or removed from the loop, or when | 
| 90 |  |  |  |  |  |  | they change their C status. The C method inspects the | 
| 91 |  |  |  |  |  |  | result bits and invokes the C or C methods on | 
| 92 |  |  |  |  |  |  | the notifiers. | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | =cut | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | =head1 CONSTRUCTOR | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | =cut | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | =head2 new | 
| 101 |  |  |  |  |  |  |  | 
| 102 |  |  |  |  |  |  | $loop = IO::Async::Loop::Poll->new( %args ) | 
| 103 |  |  |  |  |  |  |  | 
| 104 |  |  |  |  |  |  | This function returns a new instance of a C object. It | 
| 105 |  |  |  |  |  |  | takes the following named arguments: | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | =over 8 | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | =item C | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | The C object to use for notification. Optional; if a value is not | 
| 112 |  |  |  |  |  |  | given, the underlying C function is invoked directly, | 
| 113 |  |  |  |  |  |  | outside of the object wrapping. | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | =back | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | =cut | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | sub new | 
| 120 |  |  |  |  |  |  | { | 
| 121 | 84 |  |  | 84 | 1 | 319 | my $class = shift; | 
| 122 | 84 |  |  |  |  | 235 | my ( %args ) = @_; | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 84 |  |  |  |  | 202 | my $poll = delete $args{poll}; | 
| 125 |  |  |  |  |  |  |  | 
| 126 | 84 |  |  |  |  | 814 | my $self = $class->__new( %args ); | 
| 127 |  |  |  |  |  |  |  | 
| 128 | 84 |  |  |  |  | 239 | $self->{poll} = $poll; | 
| 129 | 84 |  |  |  |  | 215 | $self->{pollmask} = {}; | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 84 |  |  |  |  | 933 | return $self; | 
| 132 |  |  |  |  |  |  | } | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | =head1 METHODS | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | =cut | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | =head2 post_poll | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | $count = $loop->post_poll | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | This method checks the returned event list from a C call, | 
| 143 |  |  |  |  |  |  | and calls any of the notification methods or callbacks that are appropriate. | 
| 144 |  |  |  |  |  |  | It returns the total number of callbacks that were invoked; that is, the | 
| 145 |  |  |  |  |  |  | total number of C and C callbacks for | 
| 146 |  |  |  |  |  |  | C, and C event callbacks. | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | =cut | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | sub post_poll | 
| 151 |  |  |  |  |  |  | { | 
| 152 | 1195 |  |  | 1195 | 1 | 5162 | my $self = shift; | 
| 153 |  |  |  |  |  |  |  | 
| 154 | 1195 |  |  |  |  | 2948 | my $iowatches = $self->{iowatches}; | 
| 155 | 1195 |  |  |  |  | 3128 | my $poll      = $self->{poll}; | 
| 156 |  |  |  |  |  |  |  | 
| 157 | 1195 |  |  |  |  | 2564 | my $count = 0; | 
| 158 |  |  |  |  |  |  |  | 
| 159 | 1195 |  |  |  |  | 1958 | alarm( IO::Async::Loop->WATCHDOG_INTERVAL ) if WATCHDOG_ENABLE; | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 1195 |  |  |  |  | 7842 | foreach my $fd ( keys %$iowatches ) { | 
| 162 | 2704 | 100 |  |  |  | 9214 | my $watch = $iowatches->{$fd} or next; | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | my $events = $poll ? $poll->events( $watch->[0] ) | 
| 165 | 2703 | 100 |  |  |  | 7011 | : $self->{pollevents}{$fd}; | 
| 166 | 2703 |  |  |  |  | 3958 | if( FAKE_ISREG_READY and $self->{fake_isreg}{$fd} ) { | 
| 167 |  |  |  |  |  |  | $events |= $self->{fake_isreg}{$fd} & ( POLLIN|POLLOUT ); | 
| 168 |  |  |  |  |  |  | } | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | # We have to test separately because kernel doesn't report POLLIN when | 
| 171 |  |  |  |  |  |  | # a pipe gets closed. | 
| 172 | 2703 | 100 |  |  |  | 7212 | if( $events & (POLLIN|POLLHUP|POLLERR) ) { | 
| 173 | 1262 | 100 |  |  |  | 6955 | $count++, $watch->[1]->() if defined $watch->[1]; | 
| 174 |  |  |  |  |  |  | } | 
| 175 |  |  |  |  |  |  |  | 
| 176 | 2703 | 100 |  |  |  | 7459 | if( $events & (POLLOUT|POLLPRI|POLLHUP|POLLERR) ) { | 
| 177 | 756 | 100 |  |  |  | 2757 | $count++, $watch->[2]->() if defined $watch->[2]; | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 | 2703 | 100 |  |  |  | 8813 | if( $events & (POLLHUP|POLLERR) ) { | 
| 181 | 667 | 100 |  |  |  | 4059 | $count++, $watch->[3]->() if defined $watch->[3]; | 
| 182 |  |  |  |  |  |  | } | 
| 183 |  |  |  |  |  |  | } | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | # Since we have no way to know if the timeout occurred, we'll have to | 
| 186 |  |  |  |  |  |  | # attempt to fire any waiting timeout events anyway | 
| 187 | 1195 |  |  |  |  | 6641 | $count += $self->_manage_queues; | 
| 188 |  |  |  |  |  |  |  | 
| 189 | 1193 |  |  |  |  | 2141 | alarm( 0 ) if WATCHDOG_ENABLE; | 
| 190 |  |  |  |  |  |  |  | 
| 191 | 1193 |  |  |  |  | 7707 | return $count; | 
| 192 |  |  |  |  |  |  | } | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  | sub is_running | 
| 195 |  |  |  |  |  |  | { | 
| 196 | 1 |  |  | 1 | 0 | 5 | my $self = shift; | 
| 197 | 1 |  |  |  |  | 433 | return $self->{running}; | 
| 198 |  |  |  |  |  |  | } | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | =head2 loop_once | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | $count = $loop->loop_once( $timeout ) | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | This method calls the C method on the stored C object, | 
| 205 |  |  |  |  |  |  | passing in the value of C<$timeout>, and then runs the C method | 
| 206 |  |  |  |  |  |  | on itself. It returns the total number of callbacks invoked by the | 
| 207 |  |  |  |  |  |  | C method, or C if the underlying C method returned | 
| 208 |  |  |  |  |  |  | an error. | 
| 209 |  |  |  |  |  |  |  | 
| 210 |  |  |  |  |  |  | =cut | 
| 211 |  |  |  |  |  |  |  | 
| 212 |  |  |  |  |  |  | sub loop_once | 
| 213 |  |  |  |  |  |  | { | 
| 214 | 1193 |  |  | 1193 | 1 | 16967 | my $self = shift; | 
| 215 | 1193 |  |  |  |  | 3208 | my ( $timeout ) = @_; | 
| 216 |  |  |  |  |  |  |  | 
| 217 | 1193 |  |  |  |  | 7064 | $self->_adjust_timeout( \$timeout ); | 
| 218 |  |  |  |  |  |  |  | 
| 219 | 1193 |  |  |  |  | 2549 | $timeout = 0 if FAKE_ISREG_READY and keys %{ $self->{fake_isreg} }; | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | # Round up to nearest millisecond | 
| 222 | 1193 | 100 |  |  |  | 3438 | if( $timeout ) { | 
| 223 | 1044 |  |  |  |  | 2486 | my $mils = $timeout * 1000; | 
| 224 | 1044 |  |  |  |  | 3049 | my $fraction = $mils - int $mils; | 
| 225 | 1044 | 100 |  |  |  | 2892 | $timeout += ( 1 - $fraction ) / 1000 if $fraction; | 
| 226 |  |  |  |  |  |  | } | 
| 227 |  |  |  |  |  |  |  | 
| 228 | 1193 | 50 |  |  |  | 3907 | if( my $poll = $self->{poll} ) { | 
| 229 | 0 |  |  |  |  | 0 | my $pollret; | 
| 230 |  |  |  |  |  |  |  | 
| 231 | 0 |  |  |  |  | 0 | $self->pre_wait; | 
| 232 |  |  |  |  |  |  | # There is a bug in IO::Poll at least version 0.07, where poll with no | 
| 233 |  |  |  |  |  |  | # registered masks returns immediately, rather than waiting for a timeout | 
| 234 |  |  |  |  |  |  | # This has been reported: | 
| 235 |  |  |  |  |  |  | #   http://rt.cpan.org/Ticket/Display.html?id=25049 | 
| 236 | 0 | 0 |  |  |  | 0 | if( $poll->handles ) { | 
| 237 | 0 |  |  |  |  | 0 | $pollret = $poll->poll( $timeout ); | 
| 238 |  |  |  |  |  |  |  | 
| 239 | 0 | 0 | 0 |  |  | 0 | if( ( $pollret == -1 and $! == EINTR ) or $pollret == 0 | 
|  |  |  | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 240 |  |  |  |  |  |  | and defined $self->{sigproxy} ) { | 
| 241 |  |  |  |  |  |  | # A signal occurred and we have a sigproxy. Allow one more poll | 
| 242 |  |  |  |  |  |  | # call with zero timeout. If it finds something, keep that result. | 
| 243 |  |  |  |  |  |  | # If it finds nothing, keep -1 | 
| 244 |  |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | # Preserve $! whatever happens | 
| 246 | 0 |  |  |  |  | 0 | local $!; | 
| 247 |  |  |  |  |  |  |  | 
| 248 | 0 |  |  |  |  | 0 | my $secondattempt = $poll->poll( 0 ); | 
| 249 | 0 | 0 |  |  |  | 0 | $pollret = $secondattempt if $secondattempt > 0; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  | } | 
| 252 |  |  |  |  |  |  | else { | 
| 253 |  |  |  |  |  |  | # Workaround - we'll use select to fake a millisecond-accurate sleep | 
| 254 | 0 |  |  |  |  | 0 | $pollret = select( undef, undef, undef, $timeout ); | 
| 255 |  |  |  |  |  |  | } | 
| 256 |  |  |  |  |  |  |  | 
| 257 | 0 |  |  |  |  | 0 | $self->post_wait; | 
| 258 |  |  |  |  |  |  |  | 
| 259 | 0 | 0 |  |  |  | 0 | return undef unless defined $pollret; | 
| 260 | 0 |  |  |  |  | 0 | return $self->post_poll; | 
| 261 |  |  |  |  |  |  | } | 
| 262 |  |  |  |  |  |  | else { | 
| 263 | 1193 |  |  |  |  | 2222 | my @pollmasks = %{ $self->{pollmask} }; | 
|  | 1193 |  |  |  |  | 8314 |  | 
| 264 |  |  |  |  |  |  |  | 
| 265 | 1193 |  |  |  |  | 7224 | $self->pre_wait; | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | # Perl 5.8.x's IO::Poll::_poll gets confused with no masks | 
| 268 | 1193 |  |  |  |  | 29451 | my $pollret; | 
| 269 | 1193 | 100 |  |  |  | 3586 | if( @pollmasks ) { | 
| 270 | 1101 | 100 |  |  |  | 3298 | my $msec = defined $timeout ? $timeout * 1000 : -1; | 
| 271 | 1101 |  |  |  |  | 223476605 | $pollret = IO::Poll::_poll( $msec, @pollmasks ); | 
| 272 | 1101 | 100 | 66 |  |  | 21288 | if( $pollret == -1 and $! == EINTR or | 
|  |  |  | 66 |  |  |  |  | 
|  |  |  | 66 |  |  |  |  | 
| 273 |  |  |  |  |  |  | $pollret == 0 and $self->{sigproxy} ) { | 
| 274 | 32 |  |  |  |  | 572 | local $!; | 
| 275 |  |  |  |  |  |  |  | 
| 276 | 32 |  |  |  |  | 218 | @pollmasks = %{ $self->{pollmask} }; | 
|  | 32 |  |  |  |  | 417 |  | 
| 277 | 32 |  |  |  |  | 650 | my $secondattempt = IO::Poll::_poll( $msec, @pollmasks ); | 
| 278 | 32 | 50 |  |  |  | 729 | $pollret = $secondattempt if $secondattempt > 0; | 
| 279 |  |  |  |  |  |  | } | 
| 280 |  |  |  |  |  |  |  | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  | else { | 
| 283 |  |  |  |  |  |  | # Workaround - we'll use select to fake a millisecond-accurate sleep | 
| 284 | 92 |  |  |  |  | 63085635 | $pollret = select( undef, undef, undef, $timeout ); | 
| 285 |  |  |  |  |  |  | } | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 1193 |  |  |  |  | 12534 | $self->post_wait; | 
| 288 |  |  |  |  |  |  |  | 
| 289 | 1193 | 50 |  |  |  | 19311 | return undef unless defined $pollret; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 1193 |  |  |  |  | 9801 | $self->{pollevents} = { @pollmasks }; | 
| 292 | 1193 |  |  |  |  | 5694 | return $self->post_poll; | 
| 293 |  |  |  |  |  |  | } | 
| 294 |  |  |  |  |  |  | } | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | sub watch_io | 
| 297 |  |  |  |  |  |  | { | 
| 298 | 773 |  |  | 773 | 1 | 3442 | my $self = shift; | 
| 299 | 773 |  |  |  |  | 6923 | my %params = @_; | 
| 300 |  |  |  |  |  |  |  | 
| 301 | 773 |  |  |  |  | 8542 | $self->__watch_io( %params ); | 
| 302 |  |  |  |  |  |  |  | 
| 303 | 773 |  |  |  |  | 1969 | my $poll = $self->{poll}; | 
| 304 |  |  |  |  |  |  |  | 
| 305 | 773 |  |  |  |  | 1418 | my $handle = $params{handle}; | 
| 306 | 773 |  |  |  |  | 2173 | my $fileno = $handle->fileno; | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | my $curmask = $poll ? $poll->mask( $handle ) | 
| 309 | 773 | 100 |  |  |  | 4945 | : $self->{pollmask}{$fileno}; | 
| 310 | 773 |  | 100 |  |  | 6957 | $curmask ||= 0; | 
| 311 |  |  |  |  |  |  |  | 
| 312 | 773 |  |  |  |  | 1325 | my $mask = $curmask; | 
| 313 | 773 | 100 |  |  |  | 2342 | $params{on_read_ready}  and $mask |= POLLIN; | 
| 314 | 773 | 100 |  |  |  | 1849 | $params{on_write_ready} and $mask |= POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0); | 
| 315 | 773 | 100 |  |  |  | 1743 | $params{on_hangup}      and $mask |= POLLHUP; | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 773 |  |  |  |  | 1212 | if( FAKE_ISREG_READY and S_ISREG +(stat $handle)[2] ) { | 
| 318 |  |  |  |  |  |  | $self->{fake_isreg}{$fileno} = $mask; | 
| 319 |  |  |  |  |  |  | } | 
| 320 |  |  |  |  |  |  |  | 
| 321 | 773 | 100 |  |  |  | 2247 | return if $mask == $curmask; | 
| 322 |  |  |  |  |  |  |  | 
| 323 | 772 | 100 |  |  |  | 1778 | if( $poll ) { | 
| 324 | 4 |  |  |  |  | 11 | $poll->mask( $handle, $mask ); | 
| 325 |  |  |  |  |  |  | } | 
| 326 |  |  |  |  |  |  | else { | 
| 327 | 768 |  |  |  |  | 5295 | $self->{pollmask}{$fileno} = $mask; | 
| 328 |  |  |  |  |  |  | } | 
| 329 |  |  |  |  |  |  | } | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | sub unwatch_io | 
| 332 |  |  |  |  |  |  | { | 
| 333 | 702 |  |  | 702 | 1 | 4386 | my $self = shift; | 
| 334 | 702 |  |  |  |  | 3180 | my %params = @_; | 
| 335 |  |  |  |  |  |  |  | 
| 336 | 702 |  |  |  |  | 4549 | $self->__unwatch_io( %params ); | 
| 337 |  |  |  |  |  |  |  | 
| 338 | 702 |  |  |  |  | 2154 | my $poll = $self->{poll}; | 
| 339 |  |  |  |  |  |  |  | 
| 340 | 702 |  |  |  |  | 1335 | my $handle = $params{handle}; | 
| 341 | 702 |  |  |  |  | 1634 | my $fileno = $handle->fileno; | 
| 342 |  |  |  |  |  |  |  | 
| 343 |  |  |  |  |  |  | my $curmask = $poll ? $poll->mask( $handle ) | 
| 344 | 702 | 100 |  |  |  | 4393 | : $self->{pollmask}{$fileno}; | 
| 345 | 702 |  | 100 |  |  | 2070 | $curmask ||= 0; | 
| 346 |  |  |  |  |  |  |  | 
| 347 | 702 |  |  |  |  | 1259 | my $mask = $curmask; | 
| 348 | 702 | 100 |  |  |  | 2668 | $params{on_read_ready}  and $mask &= ~POLLIN; | 
| 349 | 702 | 100 |  |  |  | 2144 | $params{on_write_ready} and $mask &= ~(POLLOUT | (POLL_CONNECT_POLLPRI ? POLLPRI : 0)); | 
| 350 | 702 | 100 |  |  |  | 2016 | $params{on_hangup}      and $mask &= ~POLLHUP; | 
| 351 |  |  |  |  |  |  |  | 
| 352 | 702 |  |  |  |  | 1215 | if( FAKE_ISREG_READY and S_ISREG +(stat $handle)[2] ) { | 
| 353 |  |  |  |  |  |  | if( $mask ) { | 
| 354 |  |  |  |  |  |  | $self->{fake_isreg}{$handle->fileno} = $mask; | 
| 355 |  |  |  |  |  |  | } | 
| 356 |  |  |  |  |  |  | else { | 
| 357 |  |  |  |  |  |  | delete $self->{fake_isreg}{$handle->fileno}; | 
| 358 |  |  |  |  |  |  | } | 
| 359 |  |  |  |  |  |  | } | 
| 360 |  |  |  |  |  |  |  | 
| 361 | 702 | 100 |  |  |  | 1864 | return if $mask == $curmask; | 
| 362 |  |  |  |  |  |  |  | 
| 363 | 667 | 100 |  |  |  | 1672 | if( $poll ) { | 
| 364 | 3 |  |  |  |  | 9 | $poll->mask( $handle, $mask ); | 
| 365 |  |  |  |  |  |  | } | 
| 366 |  |  |  |  |  |  | else { | 
| 367 |  |  |  |  |  |  | $mask ? ( $self->{pollmask}{$fileno} = $mask ) | 
| 368 | 664 | 100 |  |  |  | 6723 | : ( delete $self->{pollmask}{$fileno} ); | 
| 369 |  |  |  |  |  |  | } | 
| 370 |  |  |  |  |  |  | } | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | =head1 AUTHOR | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | Paul Evans | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | =cut | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | 0x55AA; |