Async
view release on metacpan or search on metacpan
my $buf;
my $nr = read $self->{'PIPE'}, $buf, 8192;
if ( $nr ) {
$self->{'DATA'} .= $buf;
} elsif ( defined $nr ) { # EOF
$self->{'FINISHED'} = 1;
return 1;
} else {
$self->{'ERROR'} = "Read error: $!";
$self->{'FINISHED'} = 1;
return 1;
}
}
return 0;
}
# Return error message if an error occurred
# Return false if no error occurred
sub error { $_[0]{'ERROR'} }
# Return resulting data if async process is complete
# return undef if it is incopmplete
# a true $force argument waits for the process to complete before returning
sub result {
my ( $self, $force ) = ( shift, @_ );
if ( $self->{'FINISHED'} ) {
$self->{'DATA'};
} elsif ( $force ) {
$self->ready( $force );
$self->{'DATA'};
} else {
return;
}
}
sub DESTROY {
my $self = shift;
return if $self->{'PPID'} != $$; # created in a different process
my $pid = $self->{'PID'};
local ( $., $@, $!, $^E, $? );
kill 9, $pid; # I don't care.
waitpid $pid, 0;
}
package AsyncTimeout;
our $VERSION = '0.14';
our @ISA = 'Async';
sub new {
my ( $class, $task, $timeout, $msg ) = ( shift, @_ );
$msg = "Timed out\n" unless defined $msg;
my $newtask = sub {
local $SIG{'ALRM'} = sub { die "TIMEOUT\n" };
alarm $timeout;
my $s = eval { $task->() };
return $msg if not defined $s and $@ eq "TIMEOUT\n";
return $s;
};
$class->SUPER::new( $newtask );
}
package AsyncData;
our $VERSION = '0.14';
our @ISA = 'Async';
sub new {
require Storable;
my ( $class, $task ) = ( shift, @_ );
my $newtask = sub {
my $v = $task->();
return Storable::freeze( $v );
};
$class->SUPER::new( $newtask );
}
sub result {
require Storable;
my $self = shift;
my $rc = $self->SUPER::result( @_ );
return defined $rc ? Storable::thaw( $rc ) : $rc;
}
1;
__END__
=head1 NAME
Async - Asynchronous evaluation of Perl code (with optional timeouts)
=head1 SYNOPSIS
my $proc = Async->new( sub { any perl code you want executed } );
if ( $proc->ready ) {
# the code has finished executing
if ( $proc->error ) {
# something went wrong
} else {
$result = $proc->result; # The return value of the code
}
}
# or:
$result = $proc->result( 'force completion' ); # wait for it to finish
=head1 DESCRIPTION
This module runs some code in a separate process and retrieves its
result. Since the code is running in a separate process, your main
program can continue with whatever it was doing while the separate
code is executing. This separate code is called an I<asynchronous
computation>.
=head1 INTERFACE
To check if the asynchronous computation is complete you can call
the C<ready()>
method, which returns true if so, and false if it is still running.
After the asynchronous computation is complete, you should call the
C<error()> method to make sure that everything went all right.
C<error()> will return C<undef> if the computation completed normally,
and an error message otherwise.
Data returned by the computation can be retrieved with the C<result()>
method. The data must be a single string; any non-string value
returned by the computation will be stringified. (See AsyncData below
for how to avoid this.) If the computation has not completed yet,
C<result()> will return an undefined value.
C<result()> takes an optional parameter, C<$force>. If C<$force> is
true, then the calling process will wait until the asynchronous
computation is complete before returning.
=head2 C<AsyncTimeout>
use Async;
$proc = AsyncTimeout->new( sub { ... }, $timeout, $special );
( run in 1.521 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )