--- cvsroot/EV/EV.xs 2007/10/29 07:24:37 1.9 +++ cvsroot/EV/EV.xs 2007/10/30 12:48:29 1.14 @@ -25,7 +25,12 @@ #define TIMEOUT_NONE HUGE_VAL +#include "EV/EVAPI.h" + typedef struct event_base *Base; +typedef int Signal; + +static struct EVAPI evapi; static HV *stash_base, *stash_event; @@ -41,6 +46,34 @@ } +static int +sv_signum (SV *sig) +{ + int signum; + + if (SvIV (sig) > 0) + return SvIV (sig); + + for (signum = 1; signum < SIG_SIZE; ++signum) + if (strEQ (SvPV_nolen (sig), PL_sig_name [signum])) + return signum; + + return -1; +} + +static void +api_once (int fd, short events, double timeout, void (*cb)(int, short, void *), void *arg) +{ + if (timeout >= 0.) + { + struct timeval tv; + tv_set (&tv, timeout); + event_once (fd, events, cb, arg, &tv); + } + else + event_once (fd, events, cb, arg, 0); +} + ///////////////////////////////////////////////////////////////////////////// // Event @@ -55,7 +88,7 @@ } *Event; static double -e_now () +e_now (void) { struct timeval tv; gettimeofday (&tv, 0); @@ -167,33 +200,48 @@ { struct ev *ev = (struct ev*)arg; dSP; - - ENTER; - SAVETMPS; + I32 mark = SP - PL_stack_base; + SV *sv_self, *sv_events; + static SV *sv_events_cache; if (!(ev->ev.ev_events & EV_PERSIST) || (events & EV_TIMEOUT)) ev->active = 0; + sv_self = e_self (ev); + + if (sv_events_cache) + { + sv_events = sv_events_cache; sv_events_cache = 0; + SvIV_set (sv_events, events); + } + else + sv_events = newSViv (events); + PUSHMARK (SP); EXTEND (SP, 2); - PUSHs (sv_2mortal (e_self (ev))); - PUSHs (sv_2mortal (newSViv (events))); + PUSHs (sv_self); + PUSHs (sv_events); PUTBACK; call_sv (ev->cb, G_DISCARD | G_VOID | G_EVAL); + SP = PL_stack_base + mark; PUTBACK; + + SvREFCNT_dec (sv_self); + + if (sv_events_cache) + SvREFCNT_dec (sv_events); + else + sv_events_cache = sv_events; if (ev->interval && !ev->active) e_start (ev); - FREETMPS; - if (SvTRUE (ERRSV)) { PUSHMARK (SP); PUTBACK; call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR); + SP = PL_stack_base + mark; PUTBACK; } - - LEAVE; } ///////////////////////////////////////////////////////////////////////////// @@ -255,6 +303,7 @@ BOOT: { + int i; HV *stash = gv_stashpv ("EV", 1); static const struct { @@ -282,6 +331,20 @@ stash_base = gv_stashpv ("EV::Base" , 1); stash_event = gv_stashpv ("EV::Event", 1); + + { + SV *sv = perl_get_sv ("EV::API", TRUE); + perl_get_sv ("EV::API", TRUE); /* silence 5.10 warning */ + + evapi.ver = EV_API_VERSION; + evapi.rev = EV_API_REVISION; + evapi.now = e_now; + evapi.once = api_once; + evapi.loop = event_loop; + + sv_setiv (sv, (IV)&evapi); + SvREADONLY_on (sv); + } } double now () @@ -372,11 +435,12 @@ OUTPUT: RETVAL -Event signal (SV *signal, SV *cb) +Event signal (Signal signum, SV *cb) ALIAS: signal_ns = 1 CODE: - RETVAL = e_new (signal, EV_SIGNAL | EV_PERSIST, cb); + RETVAL = e_new (ST (0), EV_SIGNAL | EV_PERSIST, cb); + RETVAL->ev.ev_fd = signum; if (!ix) e_start (RETVAL); OUTPUT: RETVAL @@ -457,8 +521,6 @@ RETVAL SV *fh (Event ev, SV *new_fh = 0) - ALIAS: - signal = 1 CODE: RETVAL = newSVsv (ev->fh); if (items > 1) @@ -466,12 +528,34 @@ if (ev->active) event_del (&ev->ev); sv_setsv (ev->fh, new_fh); ev->ev.ev_fd = sv_fileno (ev->fh); - ev->ev.ev_events = signal ? ev->ev.ev_events | EV_SIGNAL : ev->ev.ev_events & ~EV_SIGNAL; + ev->ev.ev_events &= ev->ev.ev_events & ~EV_SIGNAL; if (ev->active) event_add (&ev->ev, e_tv (ev)); } OUTPUT: RETVAL +SV *signal (Event ev, SV *new_signal = 0) + CODE: +{ + Signal signum; + + if (items > 1) + signum = sv_signum (new_signal); /* may croak here */ + + RETVAL = newSVsv (ev->fh); + + if (items > 1) + { + if (ev->active) event_del (&ev->ev); + sv_setsv (ev->fh, new_signal); + ev->ev.ev_fd = signum; + ev->ev.ev_events |= EV_SIGNAL; + if (ev->active) event_add (&ev->ev, e_tv (ev)); + } +} + OUTPUT: + RETVAL + short events (Event ev, short new_events = EV_UNDEF) CODE: RETVAL = ev->ev.ev_events;