Async-Event-Interval
view release on metacpan or search on metacpan
lib/Async/Event/Interval.pm view on Meta::CPAN
return if $_shutting_down;
if (defined $self) {
$self->stop if $self->pid;
}
# On events with interval of zero, ForkManager runs finish(), which calls
# our destroy method. We only want to blow away the %events hash if we truly
# go out of scope
return if (caller())[0] eq 'Parallel::ForkManager::Child';
# Release any shared_scalar segments owned by this event. These are tracked
# in $self->{_shared_scalars}, not inside %events, so they can be cleaned up
# outside the %events lock.
if ($self->{_shared_scalars}) {
for my $scalar (@{ $self->{_shared_scalars} }) {
next unless ref $scalar eq 'SCALAR';
my $knot = tied $$scalar;
eval { $knot->remove } if $knot;
}
}
my $ok = eval {
_events_write(sub {
delete $events{$self->id};
$events{_event_count}--;
});
1;
};
if (! $ok) {
if (my $knot = tied(%events)) {
$knot->{_lock} = 0;
}
}
}
END {
_end(1);
}
sub _vim{} # vim navigation marker; intentionally empty
1;
__END__
=head1 NAME
Async::Event::Interval - Scheduled and one-off restartable asynchronous events
=for html
<a href="https://github.com/stevieb9/async-event-interval/actions"><img src="https://github.com/stevieb9/async-event-interval/workflows/CI/badge.svg"/></a>
<a href='https://coveralls.io/github/stevieb9/async-event-interval?branch=master'><img src='https://coveralls.io/repos/stevieb9/async-event-interval/badge.svg?branch=master&service=github' alt='Coverage Status' /></a>
=head1 SYNOPSIS
Here's an example of a simple asynchronous event that fetches JSON data from a
website every two seconds using a shared scalar variable to hold the decoded
JSON hashref, while allowing the main application to continue running in the
foreground. Multiple events can be used simultaneously if desired.
See the L</SCENARIOS/EXAMPLES> section for further usage examples.
use warnings;
use strict;
use Async::Event::Interval;
use JSON;
my $event = Async::Event::Interval->new(2, \&callback);
my $api_data_href = $event->shared_scalar;
$event->start;
while (1) {
if ($$api_data_href) {
print "Element 1 of 'data' dict is $$api_data_href->{data}[1]\n";
# ...do other things with data
}
# ...do other things
if ($event->error) {
print $event->error_message;
$event->restart;
}
}
sub callback {
my $api_json = some_web_api_call(); # '{"data": [1, 2, 3]}';
$$api_data_href = decode_json($api_json);
}
=head1 DESCRIPTION
Very basic implementation of asynchronous events triggered by a timed interval.
If a time of zero is specified, we'll run the event only once while providing
the ability to re-run it manually at any time in the future.
B<Signal handling>: The module installs C<$SIG{INT}> and C<$SIG{TERM}>
handlers at load time to ensure shared memory segments are cleaned up when the
host process is killed by a signal. The handlers stop any running event
children, remove all shared memory segments, then re-raise the signal with the
default handler so the process exits with the correct status. If you install
your own handlers for these signals, call C<Async::Event::Interval::_end(1)>
from them before exiting to avoid leaking segments.
The module also sets C<$SIG{CHLD} = 'IGNORE'> at load time to automatically
reap forked event children, preventing zombie processes. If you need to
manage child processes manually (e.g. to call C<waitpid> yourself), install
your own C<$SIG{CHLD}> handler after C<use Async::Event::Interval>.
=head1 METHODS - EVENT OPERATION
=head2 new($delay, $callback, @params)
( run in 2.746 seconds using v1.01-cache-2.11-cpan-600a1bdf6e4 )