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 )