#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include #include #include "const-c.inc" typedef int kqueue_t; struct kevent *ke2 = NULL; AV * ke2av = NULL; MODULE = IO::KQueue PACKAGE = IO::KQueue PROTOTYPES: DISABLE INCLUDE: const-xs.inc BOOT: Newz(0, ke2, 1000, struct kevent); ke2av = newAV(); av_store(ke2av, 0, (newSViv(0))); av_store(ke2av, 1, (newSViv(0))); av_store(ke2av, 2, (newSViv(0))); av_store(ke2av, 3, (newSViv(0))); av_store(ke2av, 4, (newSViv(0))); kqueue_t new(CLASS) const char * CLASS CODE: RETVAL = kqueue(); if (RETVAL == -1) { croak("kqueue() failed: %s", strerror(errno)); } OUTPUT: RETVAL void EV_SET(kq, ident, filter, flags, fflags = 0, data = 0, udata = NULL) kqueue_t kq uintptr_t ident short filter u_short flags u_short fflags intptr_t data SV * udata PREINIT: struct kevent ke; int i; PPCODE: memset(&ke, 0, sizeof(struct kevent)); if (udata) SvREFCNT_inc(udata); else udata = &PL_sv_undef; EV_SET(&ke, ident, filter, flags, fflags, data, udata); i = kevent(kq, &ke, 1, NULL, 0, NULL); if (i == -1) { croak("set kevent failed: %s", strerror(errno)); } void kevent(kq, timeout=&PL_sv_undef) kqueue_t kq SV * timeout PREINIT: int num_events, i; struct timespec t; struct kevent *ke = NULL; struct timespec *tbuf = (struct timespec *)0; I32 max_events = SvIV(get_sv("IO::KQueue::MAX_EVENTS", FALSE)); PPCODE: Newxz(ke, max_events, struct kevent); if (ke == NULL) { croak("malloc failed"); } if (timeout != &PL_sv_undef) { I32 time = SvIV(timeout); if (time >= 0) { t.tv_sec = time / 1000; t.tv_nsec = (time % 1000) * 1000000; tbuf = &t; } } num_events = kevent(kq, NULL, 0, ke, max_events, tbuf); if (num_events == -1) { Safefree(ke); croak("kevent error: %s", strerror(errno)); } /* extend it for the number of events we have */ EXTEND(SP, num_events); for (i = 0; i < num_events; i++) { AV * array = newAV(); av_push(array, newSViv(ke[i].ident)); av_push(array, newSViv(ke[i].filter)); av_push(array, newSViv(ke[i].flags)); av_push(array, newSViv(ke[i].fflags)); av_push(array, newSViv(ke[i].data)); av_push(array, SvREFCNT_inc(ke[i].udata)); PUSHs(sv_2mortal(newRV_noinc((SV*)array))); } Safefree(ke); int kevent2(kq, timeout=&PL_sv_undef) kqueue_t kq SV * timeout PREINIT: int num_events, i; struct timespec t; struct timespec *tbuf = (struct timespec *)0; CODE: if (timeout != &PL_sv_undef) { I32 time = SvIV(timeout); if (time >= 0) { t.tv_sec = time / 1000; t.tv_nsec = (time % 1000) * 1000000; tbuf = &t; } } RETVAL = kevent(kq, NULL, 0, ke2, 1000, tbuf); OUTPUT: RETVAL SV* get_kev(kq, i) kqueue_t kq int i PREINIT: dXSTARG; CODE: if (i < 0 || i >= 1000) { croak("Invalid kevent id: %d", i); } sv_setiv(AvARRAY(ke2av)[0], ke2[i-1].ident); sv_setiv(AvARRAY(ke2av)[1], ke2[i-1].filter); sv_setiv(AvARRAY(ke2av)[2], ke2[i-1].flags); sv_setiv(AvARRAY(ke2av)[3], ke2[i-1].fflags); sv_setiv(AvARRAY(ke2av)[4], ke2[i-1].data); av_store(ke2av, 5, SvREFCNT_inc(ke2[i-1].udata)); RETVAL = newRV_inc((SV*) ke2av); OUTPUT: RETVAL