Async-Interrupt
view release on metacpan or search on metacpan
Interrupt.xs view on Meta::CPAN
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 */
}
}
MODULE = Async::Interrupt PACKAGE = Async::Interrupt
BOOT:
old_sighandler = PL_sighandlerp;
PL_sighandlerp = async_sighandler;
sig_pending = &PL_sig_pending;
psig_pend = PL_psig_pend;
asyncs = newAV ();
CvNODEBUG_on (get_cv ("Async::Interrupt::scope_block", 0)); /* otherwise calling scope can be the debugger */
PROTOTYPES: DISABLE
void
_alloc (SV *cb, void *c_cb, void *c_arg, SV *fh_r, SV *fh_w, SV *signl, SV *pvalue)
PPCODE:
{
SV *cv = SvOK (cb) ? SvREFCNT_inc (s_get_cv_croak (cb)) : 0;
async_t *async;
Newz (0, async, 1, async_t);
XPUSHs (sv_2mortal (newSViv (PTR2IV (async))));
/* TODO: need to bless right now to ensure deallocation */
av_push (asyncs, TOPs);
SvGETMAGIC (fh_r); SvGETMAGIC (fh_w);
if (SvOK (fh_r) || SvOK (fh_w))
{
int fd_r = s_fileno_croak (fh_r, 0);
int fd_w = s_fileno_croak (fh_w, 1);
async->fh_r = newSVsv (fh_r);
async->fh_w = newSVsv (fh_w);
async->ep.fd [0] = fd_r;
async->ep.fd [1] = fd_w;
async->ep.len = 1;
async->fd_enable = 1;
}
async->value = SvROK (pvalue)
? SvREFCNT_inc_NN (SvRV (pvalue))
: NEWSV (0, 0);
sv_setiv (async->value, 0);
SvIOK_only (async->value); /* just to be sure */
SvREADONLY_on (async->value);
async->valuep = &(SvIVX (async->value));
async->autodrain = 1;
async->cb = cv;
async->c_cb = c_cb;
async->c_arg = c_arg;
async->signum = SvOK (signl) ? s_signum_croak (signl) : 0;
if (async->signum)
{
if (async->signum < 0)
croak ("Async::Interrupt::new got passed illegal signal name or number: %s", SvPV_nolen (signl));
sig_async [async->signum] = async;
setsig (async->signum, async_sigsend);
}
}
void
signal_hysteresis (async_t *async, int enable)
CODE:
async->hysteresis = enable;
void
signal_func (async_t *async)
PPCODE:
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (PTR2IV (async_signal))));
PUSHs (sv_2mortal (newSViv (PTR2IV (async))));
void
scope_block_func (SV *self)
PPCODE:
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (PTR2IV (scope_block))));
PUSHs (sv_2mortal (newSViv (PTR2IV (SvRV (self)))));
IV
c_var (async_t *async)
CODE:
RETVAL = PTR2IV (async->valuep);
OUTPUT:
RETVAL
void
handle (async_t *async)
CODE:
handle_async (async);
void
signal (async_t *async, int value = 1)
CODE:
async_signal (async, value);
void
block (async_t *async)
CODE:
block (async);
void
unblock (async_t *async)
CODE:
unblock (async);
void
scope_block (SV *self)
CODE:
scope_block (SvRV (self));
void
pipe_enable (async_t *async)
ALIAS:
pipe_enable = 1
pipe_disable = 0
CODE:
async->fd_enable = ix;
int
pipe_fileno (async_t *async)
CODE:
if (!async->ep.len)
{
int res;
/*block (async);*//*TODO*/
res = s_epipe_new (&async->ep);
async->fd_enable = 1;
/*unblock (async);*//*TODO*/
if (res < 0)
croak ("Async::Interrupt: unable to initialize event pipe");
}
Interrupt.xs view on Meta::CPAN
void
DESTROY (SV *self)
CODE:
{
int i;
SV *async_sv = SvRV (self);
async_t *async = SvASYNC_nrv (async_sv);
for (i = AvFILLp (asyncs); i >= 0; --i)
if (AvARRAY (asyncs)[i] == async_sv)
{
AvARRAY (asyncs)[i] = AvARRAY (asyncs)[AvFILLp (asyncs)];
av_pop (asyncs);
goto found;
}
if (!PL_dirty)
warn ("Async::Interrupt::DESTROY could not find async object in list of asyncs, please report");
found:
if (async->signum)
setsig (async->signum, SIG_DFL);
if (!async->fh_r && async->ep.len)
s_epipe_destroy (&async->ep);
SvREFCNT_dec (async->fh_r);
SvREFCNT_dec (async->fh_w);
SvREFCNT_dec (async->cb);
SvREFCNT_dec (async->value);
Safefree (async);
}
SV *
sig2num (SV *signame_or_number)
ALIAS:
sig2num = 0
sig2name = 1
PROTOTYPE: $
CODE:
{
int signum = s_signum (signame_or_number);
if (signum < 0)
RETVAL = &PL_sv_undef;
else if (ix)
RETVAL = newSVpv (PL_sig_name [signum], 0);
else
RETVAL = newSViv (signum);
}
OUTPUT:
RETVAL
MODULE = Async::Interrupt PACKAGE = Async::Interrupt::EventPipe PREFIX = s_epipe_
void
new (const char *klass)
PPCODE:
{
s_epipe *epp;
Newz (0, epp, 1, s_epipe);
XPUSHs (sv_setref_iv (sv_newmortal (), klass, PTR2IV (epp)));
if (s_epipe_new (epp) < 0)
croak ("Async::Interrupt::EventPipe: unable to create new event pipe");
}
void
filenos (s_epipe *epp)
PPCODE:
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (epp->fd [0])));
PUSHs (sv_2mortal (newSViv (epp->fd [1])));
int
fileno (s_epipe *epp)
ALIAS:
fileno = 0
fileno_r = 0
fileno_w = 1
CODE:
RETVAL = epp->fd [ix];
OUTPUT:
RETVAL
int
type (s_epipe *epp)
CODE:
RETVAL = epp->len;
OUTPUT:
RETVAL
void
s_epipe_signal (s_epipe *epp)
void
s_epipe_drain (s_epipe *epp)
void
signal_func (s_epipe *epp)
ALIAS:
drain_func = 1
PPCODE:
EXTEND (SP, 2);
PUSHs (sv_2mortal (newSViv (PTR2IV (ix ? s_epipe_drain : s_epipe_signal))));
PUSHs (sv_2mortal (newSViv (PTR2IV (epp))));
void
s_epipe_wait (s_epipe *epp)
void
s_epipe_renew (s_epipe *epp)
void
DESTROY (s_epipe *epp)
CODE:
s_epipe_destroy (epp);
( run in 0.835 second using v1.01-cache-2.11-cpan-71847e10f99 )