Acme-Sort-Sleep

 view release on metacpan or  search on metacpan

local/lib/perl5/IO/Async/Loop.pm  view on Meta::CPAN

use IO::Async::OS;

use constant HAVE_SIGNALS => IO::Async::OS->HAVE_SIGNALS;
use constant HAVE_POSIX_FORK => IO::Async::OS->HAVE_POSIX_FORK;
use constant HAVE_THREADS => IO::Async::OS->HAVE_THREADS;

# Never sleep for more than 1 second if a signal proxy is registered, to avoid
# a borderline race condition.
# There is a race condition in perl involving signals interacting with XS code
# that implements blocking syscalls. There is a slight chance a signal will
# arrive in the XS function, before the blocking itself. Perl will not run our
# (safe) deferred signal handler in this case. To mitigate this, if we have a
# signal proxy, we'll adjust the maximal timeout. The signal handler will be 
# run when the XS function returns. 
our $MAX_SIGWAIT_TIME = 1;

# Also, never sleep for more than 1 second if the OS does not support signals
# and we have child watches registered (so we must use waitpid() polling)
our $MAX_CHILDWAIT_TIME = 1;

# Maybe our calling program will have a suggested hint of a specific Loop
# class or list of classes to use
our $LOOP;

# Undocumented; used only by the test scripts.
# Setting this value true will avoid the IO::Async::Loop::$^O candidate in the
# magic constructor
our $LOOP_NO_OS;

# SIGALRM handler for watchdog
$SIG{ALRM} = sub {
   # There are two extra frames here; this one and the signal handler itself
   local $Carp::CarpLevel = $Carp::CarpLevel + 2;
   if( WATCHDOG_SIGABRT ) {
      print STDERR Carp::longmess( "Watchdog timeout" );
      kill ABRT => $$;
   }
   else {
      Carp::confess( "Watchdog timeout" );
   }
} if WATCHDOG_ENABLE;

$SIG{PIPE} = "IGNORE" if ( $SIG{PIPE} || "" ) eq "DEFAULT";

=head1 NAME

C<IO::Async::Loop> - core loop of the C<IO::Async> framework

=head1 SYNOPSIS

 use IO::Async::Stream;
 use IO::Async::Timer::Countdown;

 use IO::Async::Loop;

 my $loop = IO::Async::Loop->new;

 $loop->add( IO::Async::Timer::Countdown->new(
    delay => 10,
    on_expire => sub { print "10 seconds have passed\n" },
 )->start );

 $loop->add( IO::Async::Stream->new_for_stdin(
    on_read => sub {
       my ( $self, $buffref, $eof ) = @_;

       while( $$buffref =~ s/^(.*)\n// ) {
          print "You typed a line $1\n";
       }

       return 0;
    },
 ) );

 $loop->run;

=head1 DESCRIPTION

This module provides an abstract class which implements the core loop of the
L<IO::Async> framework. Its primary purpose is to store a set of
L<IO::Async::Notifier> objects or subclasses of them. It handles all of the
lower-level set manipulation actions, and leaves the actual IO readiness 
testing/notification to the concrete class that implements it. It also
provides other functionality such as signal handling, child process managing,
and timers.

See also the two bundled Loop subclasses:

=over 4

=item L<IO::Async::Loop::Select>

=item L<IO::Async::Loop::Poll>

=back

Or other subclasses that may appear on CPAN which are not part of the core
L<IO::Async> distribution.

=head2 Ignoring SIGPIPE

Since version I<0.66> loading this module automatically ignores C<SIGPIPE>, as
it is highly unlikely that the default-terminate action is the best course of
action for an L<IO::Async>-based program to take. If at load time the handler
disposition is still set as C<DEFAULT>, it is set to ignore. If already
another handler has been placed there by the program code, it will be left
undisturbed.

=cut

# Internal constructor used by subclasses
sub __new
{
   my $class = shift;

   # Detect if the API version provided by the subclass is sufficient
   $class->can( "API_VERSION" ) or
      die "$class is too old for IO::Async $VERSION; it does not provide \->API_VERSION\n";

   $class->API_VERSION >= NEED_API_VERSION or
      die "$class is too old for IO::Async $VERSION; we need API version >= ".NEED_API_VERSION.", it provides ".$class->API_VERSION."\n";

local/lib/perl5/IO/Async/Loop.pm  view on Meta::CPAN

}

=head2 stop

   $loop->stop( @result )

Stops the inner-most C<run> method currently in progress, causing it to return
the given C<@result>.

This method is a recent addition and may not be supported by all the
C<IO::Async::Loop> subclasses currently available on CPAN.

=cut

sub stop
{
   my $self = shift;

   @{ $self->{result} } = @_;
   undef $self->{running};
}

=head2 loop_forever

   $loop->loop_forever

A synonym for C<run>, though this method does not return a result.

=cut

sub loop_forever
{
   my $self = shift;
   $self->run;
   return;
}

=head2 loop_stop

   $loop->loop_stop

A synonym for C<stop>, though this method does not pass any results.

=cut

sub loop_stop
{
   my $self = shift;
   $self->stop;
}

=head2 post_fork

   $loop->post_fork

The base implementation of this method does nothing. It is provided in case
some Loop subclasses should take special measures after a C<fork()> system
call if the main body of the program should survive in both running processes.

This may be required, for example, in a long-running server daemon that forks
multiple copies on startup after opening initial listening sockets. A loop
implementation that uses some in-kernel resource that becomes shared after
forking (for example, a Linux C<epoll> or a BSD C<kqueue> filehandle) would
need recreating in the new child process before the program can continue.

=cut

sub post_fork
{
   # empty
}

###########
# Futures #
###########

=head1 FUTURE SUPPORT

The following methods relate to L<IO::Async::Future> objects.

=cut

=head2 new_future

   $future = $loop->new_future

Returns a new L<IO::Async::Future> instance with a reference to the Loop.

=cut

sub new_future
{
   my $self = shift;
   require IO::Async::Future;
   return IO::Async::Future->new( $self );
}

=head2 await

   $loop->await( $future )

Blocks until the given future is ready, as indicated by its C<is_ready> method.
As a convenience it returns the future, to simplify code:

 my @result = $loop->await( $future )->get;

=cut

sub await
{
   my $self = shift;
   my ( $future ) = @_;

   $self->loop_once until $future->is_ready;

   return $future;
}

=head2 await_all

   $loop->await_all( @futures )



( run in 0.811 second using v1.01-cache-2.11-cpan-39bf76dae61 )