Async-Interrupt
view release on metacpan or search on metacpan
Interrupt.pm view on Meta::CPAN
C<$value> must be in the valid range for a C<sig_atomic_t>, except C<0>
(1..127 is portable).
=item $async->handle
Calls the callback if the object is pending.
This method does not need to be called normally, as it will be invoked
automatically. However, it can be used to force handling of outstanding
interrupts while the object is blocked.
One reason why one might want to do that is when you want to switch
from asynchronous interruptions to synchronous one, using e.g. an event
loop. To do that, one would first C<< $async->block >> the interrupt
object, then register a read watcher on the C<pipe_fileno> that calls C<<
$async->handle >>.
This disables asynchronous interruptions, but ensures that interrupts are
handled by the event loop.
Interrupt.xs view on Meta::CPAN
typedef struct {
SV *cb;
void (*c_cb)(pTHX_ void *c_arg, int value);
void *c_arg;
SV *fh_r, *fh_w;
SV *value;
int signum;
int autodrain;
ANY *scope_savestack;
volatile int blocked;
s_epipe ep;
int fd_wlen;
atomic_t fd_enable;
atomic_t pending;
volatile IV *valuep;
atomic_t hysteresis;
} async_t;
static AV *asyncs;
Interrupt.xs view on Meta::CPAN
if (async->hysteresis)
setsig (async->signum, SIG_IGN);
*async->valuep = value ? value : 1;
ECB_MEMORY_FENCE_RELEASE;
async->pending = 1;
ECB_MEMORY_FENCE_RELEASE;
async_pending = 1;
ECB_MEMORY_FENCE_RELEASE;
if (!async->blocked)
{
psig_pend [9] = 1;
ECB_MEMORY_FENCE_RELEASE;
*sig_pending = 1;
ECB_MEMORY_FENCE_RELEASE;
}
if (!pending && async->fd_enable && async->ep.len)
s_epipe_signal (&async->ep);
}
Interrupt.xs view on Meta::CPAN
ECB_MEMORY_FENCE_ACQUIRE;
async_pending = 0;
for (i = AvFILLp (asyncs); i >= 0; --i)
{
SV *async_sv = AvARRAY (asyncs)[i];
async_t *async = SvASYNC_nrv (async_sv);
if (async->pending && !async->blocked)
{
/* temporarily keep a refcount */
SvREFCNT_inc (async_sv);
handle_async (async);
SvREFCNT_dec (async_sv);
/* the handler could have deleted any number of asyncs */
if (i > AvFILLp (asyncs))
i = AvFILLp (asyncs);
}
Interrupt.xs view on Meta::CPAN
#else
static Signal_t async_sighandler (int signum)
{
if (signum == 9)
handle_asyncs ();
else
old_sighandler (signum);
}
#endif
#define block(async) ++(async)->blocked
static void
unblock (async_t *async)
{
--async->blocked;
if (async->pending && !async->blocked)
handle_async (async);
}
static void
scope_block_cb (pTHX_ void *async_sv)
{
async_t *async = SvASYNC_nrv ((SV *)async_sv);
async->scope_savestack = 0;
unblock (async);
SvREFCNT_dec (async_sv);
}
static void
scope_block (SV *async_sv)
{
async_t *async = SvASYNC_nrv (async_sv);
/* as a heuristic, we skip the scope block if we already are blocked */
/* and the existing scope block used the same savestack */
if (!async->scope_savestack || async->scope_savestack != PL_savestack)
{
async->scope_savestack = PL_savestack;
block (async);
LEAVE; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
SAVEDESTRUCTOR_X (scope_block_cb, (void *)SvREFCNT_inc (async_sv));
ENTER; /* unfortunately, perl sandwiches XS calls into ENTER/LEAVE */
the name might imply, do anything with POSIX signals).
$value must be in the valid range for a "sig_atomic_t", except 0
(1..127 is portable).
$async->handle
Calls the callback if the object is pending.
This method does not need to be called normally, as it will be
invoked automatically. However, it can be used to force handling of
outstanding interrupts while the object is blocked.
One reason why one might want to do that is when you want to switch
from asynchronous interruptions to synchronous one, using e.g. an
event loop. To do that, one would first "$async->block" the
interrupt object, then register a read watcher on the "pipe_fileno"
that calls "$async->handle".
This disables asynchronous interruptions, but ensures that
interrupts are handled by the event loop.
( run in 0.510 second using v1.01-cache-2.11-cpan-49f99fa48dc )