Async-Interrupt

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

    Finally, the I/O callback for the event pipe handles the signals:

       sub _signal_check {
          # drain the pipe first
          $SIGPIPE->drain;

          # two loops, just to be sure
          while (%SIGNAL_RECEIVED) {
             for (keys %SIGNAL_RECEIVED) {
                delete $SIGNAL_RECEIVED{$_};
                warn "signal $_ received\n";
             }
          }
       }

  Interrupt perl from another thread
    This example interrupts the Perl interpreter from another thread, via
    the XS API. This is used by e.g. the EV::Loop::Async module.

    On the Perl level, a new loop object (which contains the thread) is
    created, by first calling some XS constructor, querying the C-level
    callback function and feeding that as the "c_cb" into the
    Async::Interrupt constructor:

       my $self = XS_thread_constructor;
       my ($c_func, $c_arg) = _c_func $self; # return the c callback
       my $asy = new Async::Interrupt c_cb => [$c_func, $c_arg];

    Then the newly created Interrupt object is queried for the signaling
    function that the newly created thread should call, and this is in turn
    told to the thread object:

       _attach $self, $asy->signal_func;

    So to repeat: first the XS object is created, then it is queried for the
    callback that should be called when the Interrupt object gets signalled.

    Then the interrupt object is queried for the callback function that the
    thread should call to signal the Interrupt object, and this callback is
    then attached to the thread.

    You have to be careful that your new thread is not signalling before the
    signal function was configured, for example by starting the background
    thread only within "_attach".

    That concludes the Perl part.

    The XS part consists of the actual constructor which creates a thread,
    which is not relevant for this example, and two functions, "_c_func",
    which returns the Perl-side callback, and "_attach", which configures
    the signalling functioon that is safe toc all from another thread. For
    simplicity, we will use global variables to store the functions,
    normally you would somehow attach them to $self.

    The "c_func" simply returns the address of a static function and
    arranges for the object pointed to by $self to be passed to it, as an
    integer:

       void
       _c_func (SV *loop)
               PPCODE:
               EXTEND (SP, 2);
               PUSHs (sv_2mortal (newSViv (PTR2IV (c_func))));
               PUSHs (sv_2mortal (newSViv (SvRV (loop))));

    This would be the callback (since it runs in a normal Perl context, it
    is permissible to manipulate Perl values):

       static void
       c_func (pTHX_ void *loop_, int value)
       {
         SV *loop_object = (SV *)loop_;
         ...
       }

    And this attaches the signalling callback:

       static void (*my_sig_func) (void *signal_arg, int value);
       static void *my_sig_arg;

       void
       _attach (SV *loop_, IV sig_func, void *sig_arg)
               CODE:
       {
               my_sig_func = sig_func;
               my_sig_arg  = sig_arg;

               /* now run the thread */
               thread_create (&u->tid, l_run, 0);
       }

    And "l_run" (the background thread) would eventually call the signaling
    function:

       my_sig_func (my_sig_arg, 0);

    You can have a look at EV::Loop::Async for an actual example using
    intra-thread communication, locking and so on.

THE Async::Interrupt CLASS
    $async = new Async::Interrupt key => value...
        Creates a new Async::Interrupt object. You may only use async
        notifications on this object while it exists, so you need to keep a
        reference to it at all times while it is used.

        Optional constructor arguments include (normally you would specify
        at least one of "cb" or "c_cb").

        cb => $coderef->($value)
            Registers a perl callback to be invoked whenever the async
            interrupt is signalled.

            Note that, since this callback can be invoked at basically any
            time, it must not modify any well-known global variables such as
            $/ without restoring them again before returning.

            The exceptions are $! and $@, which are saved and restored by
            Async::Interrupt.

            If the callback should throw an exception, then it will be
            caught, and $Async::Interrupt::DIED will be called with $@



( run in 0.470 second using v1.01-cache-2.11-cpan-71847e10f99 )