#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include "EVAPI.h" static GMainContext * get_gcontext (SV *context) { if (!SvOK (context)) return g_main_context_default (); croak ("only the default context is currently supported."); } static void timeout_cb (EV_P_ ev_timer *w, int revents) { ev_unloop (EV_A, EVUNLOOP_ONE); } typedef struct { struct ev_io io; int *got_events; GPollFD *pfd; } slot; static void io_cb (EV_P_ ev_io *w, int revents) { slot *s = (slot *)w; int oev = s->pfd->revents; s->pfd->revents |= s->pfd->events & ((revents & EV_READ ? G_IO_IN : 0) | (revents & EV_READ ? G_IO_OUT : 0)); if (!oev && s->pfd->revents) ++*(s->got_events); ev_unloop (EV_A, EVUNLOOP_ONE); } static gint event_poll_func (GPollFD *fds, guint nfds, gint timeout) { dSP; // yes, I use C99. If your compiler barfs here, fix it, but don't // tell me your compiler vendor was too incompetent to implement // the C standard within the last eight years. ev_timer to; slot slots[nfds]; int got_events = 0; int n; for (n = 0; n < nfds; ++n) { GPollFD *pfd = fds + n; slot *s = slots + n; pfd->revents = 0; s->pfd = pfd; s->got_events = &got_events; ev_io_init ( &s->io, io_cb, pfd->fd, (pfd->events & G_IO_IN ? EV_READ : 0) | (pfd->events & G_IO_OUT ? EV_WRITE : 0) ); ev_io_start (EV_DEFAULT, &s->io); } if (timeout >= 0) { ev_timer_init (&to, timeout_cb, timeout * 1e-3, 0.); ev_timer_start (EV_DEFAULT, &to); } ev_loop (EV_DEFAULT, 0); if (timeout >= 0) ev_timer_stop (EV_DEFAULT, &to); for (n = 0; n < nfds; ++n) ev_io_stop (EV_DEFAULT, &slots[n].io); return got_events; } MODULE = Glib::EV PACKAGE = Glib::EV PROTOTYPES: ENABLE BOOT: { I_EV_API ("Glib::EV"); } long install (SV *context) CODE: { GMainContext *ctx = get_gcontext (context); RETVAL = (long)g_main_context_get_poll_func (ctx); g_main_context_set_poll_func (ctx, event_poll_func); } OUTPUT: RETVAL void uninstall (SV *context, long prev_poll_func) CODE: { GMainContext *ctx = get_gcontext (context); g_main_context_set_poll_func (ctx, (GPollFunc) prev_poll_func); }