--- cvsroot/EV/EV.xs 2007/10/31 11:52:11 1.17 +++ cvsroot/EV/EV.xs 2007/10/31 21:34:45 1.26 @@ -2,15 +2,12 @@ #include "perl.h" #include "XSUB.h" -#include -#include +/*#include */ #define TIMEOUT_NONE HUGE_VAL +#define HAVE_EPOLL 1 -#define EV_COMMON \ - SV *self; /* contains this struct */ \ - SV *cb_sv, *fh; - +#define EV_PROTOTYPES 1 #include "EV/EVAPI.h" #include "libev/ev.c" @@ -27,7 +24,9 @@ *stash_periodic, *stash_signal, *stash_idle, - *stash_check; + *stash_prepare, + *stash_check, + *stash_child; static int sv_signum (SV *sig) @@ -44,21 +43,6 @@ return -1; } -static void -api_once (int fd, short events, double timeout, void (*cb)(int, short, void *), void *arg) -{ -#if 0 - 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); -#endif -} - ///////////////////////////////////////////////////////////////////////////// // Event @@ -122,7 +106,7 @@ { dSP; I32 mark = SP - PL_stack_base; - SV *sv_self, *sv_events; + SV *sv_self, *sv_events, *sv_status = 0; static SV *sv_events_cache; sv_self = newRV_inc (w->self); /* w->self MUST be blessed by now */ @@ -139,11 +123,16 @@ EXTEND (SP, 2); PUSHs (sv_self); PUSHs (sv_events); + + if (revents & EV_CHILD) + XPUSHs (sv_status = newSViv (((struct ev_child *)w)->status)); + PUTBACK; call_sv (w->cb_sv, G_DISCARD | G_VOID | G_EVAL); SP = PL_stack_base + mark; PUTBACK; SvREFCNT_dec (sv_self); + SvREFCNT_dec (sv_status); if (sv_events_cache) SvREFCNT_dec (sv_events); @@ -213,11 +202,16 @@ } #endif +#define CHECK_REPEAT(repeat) if (repeat < 0.) \ + croak (# repeat " value must be >= 0"); + ///////////////////////////////////////////////////////////////////////////// // XS interface functions MODULE = EV PACKAGE = EV PREFIX = ev_ +PROTOTYPES: ENABLE + BOOT: { int i; @@ -228,6 +222,7 @@ IV iv; } *civ, const_iv[] = { # define const_iv(pfx, name) { # name, (IV) pfx ## name }, + const_iv (EV_, UNDEF) const_iv (EV_, NONE) const_iv (EV_, TIMEOUT) const_iv (EV_, READ) @@ -235,6 +230,7 @@ const_iv (EV_, SIGNAL) const_iv (EV_, IDLE) const_iv (EV_, CHECK) + const_iv (EV_, ERROR) const_iv (EV, LOOP_ONESHOT) const_iv (EV, LOOP_NONBLOCK) @@ -254,7 +250,9 @@ stash_periodic = gv_stashpv ("EV::Periodic", 1); stash_signal = gv_stashpv ("EV::Signal" , 1); stash_idle = gv_stashpv ("EV::Idle" , 1); + stash_prepare = gv_stashpv ("EV::Prepare" , 1); stash_check = gv_stashpv ("EV::Check" , 1); + stash_child = gv_stashpv ("EV::Child" , 1); { SV *sv = perl_get_sv ("EV::API", TRUE); @@ -263,7 +261,6 @@ /* the poor man's shared library emulator */ evapi.ver = EV_API_VERSION; evapi.rev = EV_API_REVISION; - evapi.once = api_once; evapi.sv_fileno = sv_fileno; evapi.sv_signum = sv_signum; evapi.now = &ev_now; @@ -271,6 +268,7 @@ evapi.loop_done = &ev_loop_done; evapi.time = ev_time; evapi.loop = ev_loop; + evapi.once = ev_once; evapi.io_start = evio_start; evapi.io_stop = evio_stop; evapi.timer_start = evtimer_start; @@ -282,8 +280,12 @@ evapi.signal_stop = evsignal_stop; evapi.idle_start = evidle_start; evapi.idle_stop = evidle_stop; + evapi.prepare_start = evprepare_start; + evapi.prepare_stop = evprepare_stop; evapi.check_start = evcheck_start; evapi.check_stop = evcheck_stop; + evapi.child_start = evchild_start; + evapi.child_stop = evchild_stop; sv_setiv (sv, (IV)&evapi); SvREADONLY_on (sv); @@ -326,6 +328,8 @@ struct ev_timer *timer (NV after, NV repeat, SV *cb) ALIAS: timer_ns = 1 + INIT: + CHECK_REPEAT (repeat); CODE: RETVAL = e_new (sizeof (struct ev_timer), cb); evtimer_set (RETVAL, after, repeat); @@ -336,6 +340,8 @@ struct ev_periodic *periodic (NV at, NV interval, SV *cb) ALIAS: periodic_ns = 1 + INIT: + CHECK_REPEAT (interval); CODE: RETVAL = e_new (sizeof (struct ev_periodic), cb); evperiodic_set (RETVAL, at, interval); @@ -363,6 +369,16 @@ OUTPUT: RETVAL +struct ev_prepare *prepare (SV *cb) + ALIAS: + prepare_ns = 1 + CODE: + RETVAL = e_new (sizeof (struct ev_prepare), cb); + evprepare_set (RETVAL); + if (!ix) evprepare_start (RETVAL); + OUTPUT: + RETVAL + struct ev_check *check (SV *cb) ALIAS: check_ns = 1 @@ -373,6 +389,16 @@ OUTPUT: RETVAL +struct ev_child *child (int pid, SV *cb) + ALIAS: + check_ns = 1 + CODE: + RETVAL = e_new (sizeof (struct ev_check), cb); + evchild_set (RETVAL, pid); + if (!ix) evchild_start (RETVAL); + OUTPUT: + RETVAL + PROTOTYPES: DISABLE @@ -397,6 +423,10 @@ void evio_stop (struct ev_io *w) +void DESTROY (struct ev_io *w) + CODE: + evio_stop (w); + void set (struct ev_io *w, SV *fh, int events) CODE: { @@ -452,6 +482,10 @@ void evsignal_stop (struct ev_signal *w) +void DESTROY (struct ev_signal *w) + CODE: + evsignal_stop (w); + void set (struct ev_signal *w, SV *signal = 0) CODE: { @@ -468,12 +502,22 @@ MODULE = EV PACKAGE = EV::Timer PREFIX = evtimer_ void evtimer_start (struct ev_timer *w) + INIT: + CHECK_REPEAT (w->repeat); void evtimer_stop (struct ev_timer *w) void evtimer_again (struct ev_timer *w) + INIT: + CHECK_REPEAT (w->repeat); + +void DESTROY (struct ev_timer *w) + CODE: + evtimer_stop (w); void set (struct ev_timer *w, NV after, NV repeat = 0.) + INIT: + CHECK_REPEAT (repeat); CODE: { int active = w->active; @@ -485,10 +529,18 @@ MODULE = EV PACKAGE = EV::Periodic PREFIX = evperiodic_ void evperiodic_start (struct ev_periodic *w) + INIT: + CHECK_REPEAT (w->interval); void evperiodic_stop (struct ev_periodic *w) +void DESTROY (struct ev_periodic *w) + CODE: + evperiodic_stop (w); + void set (struct ev_periodic *w, NV at, NV interval = 0.) + INIT: + CHECK_REPEAT (interval); CODE: { int active = w->active; @@ -503,12 +555,55 @@ void evidle_stop (struct ev_idle *w) +void DESTROY (struct ev_idle *w) + CODE: + evidle_stop (w); + +MODULE = EV PACKAGE = EV::Prepare PREFIX = evcheck_ + +void evprepare_start (struct ev_prepare *w) + +void evprepare_stop (struct ev_prepare *w) + +void DESTROY (struct ev_prepare *w) + CODE: + evidle_prepare (w); + MODULE = EV PACKAGE = EV::Check PREFIX = evcheck_ void evcheck_start (struct ev_check *w) void evcheck_stop (struct ev_check *w) +void DESTROY (struct ev_check *w) + CODE: + evidle_check (w); + +MODULE = EV PACKAGE = EV::Child PREFIX = evchild_ + +void evchild_start (struct ev_child *w) + +void evchild_stop (struct ev_child *w) + +void DESTROY (struct ev_child *w) + CODE: + evidle_child (w); + +void set (struct ev_child *w, int pid) + CODE: +{ + int active = w->active; + if (active) evchild_stop (w); + evchild_set (w, pid); + if (active) evchild_start (w); +} + +int status (struct ev_child *w) + CODE: + RETVAL = w->status; + OUTPUT: + RETVAL + #if 0 MODULE = EV PACKAGE = EV::DNS PREFIX = evdns_