ext/sleepy_penguin/kqueue.c in sleepy_penguin-3.4.1 vs ext/sleepy_penguin/kqueue.c in sleepy_penguin-3.5.0

- old
+ new

@@ -41,10 +41,11 @@ static ID id_for_fd; static VALUE mEv, mEvFilt, mNote, mVQ; struct kq_per_thread { VALUE io; + VALUE changelist; int fd; int nchanges; int nevents; int capa; struct timespec *ts; @@ -70,11 +71,11 @@ errno = save_errno; return 1; } -static struct kq_per_thread *kpt_get(VALUE self, int nchanges, int nevents) +static struct kq_per_thread *kpt_get(int nchanges, int nevents) { struct kq_per_thread *kpt; size_t size; int max = nchanges > nevents ? nchanges : nevents; @@ -87,12 +88,10 @@ size = sizeof(struct kq_per_thread) + sizeof(struct kevent) * max; kpt = rb_sp_gettlsbuf(&size); kpt->capa = max; kpt->nchanges = nchanges; kpt->nevents = nevents; - kpt->io = self; - kpt->fd = rb_sp_fileno(kpt->io); return kpt; } /* @@ -100,15 +99,14 @@ * SleepyPenguin::Kqueue::IO.new -> Kqueue::IO object * * Creates a new Kqueue::IO object. This is a wrapper around the kqueue(2) * system call which creates a Ruby IO object around the kqueue descriptor. * - * kqueue descriptors are automatically invalidated across fork, so care - * must be taken when forking. + * kqueue descriptors are automatically invalidated by the OS across fork, + * so care must be taken when forking. * Setting IO#autoclose=false is recommended for applications which fork - * after kqueue creation. Ruby 1.8 does not have IO#autoclose=, so using - * this class is not recommended under Ruby 1.8 + * after kqueue creation. */ static VALUE s_new(VALUE klass) { VALUE rv; int fd = kqueue(); @@ -201,15 +199,20 @@ kpt->events, kpt->nevents, kpt->ts); return (VALUE)nevents; } +static void changelist_prepare(struct kevent *, VALUE); + static VALUE do_kevent(struct kq_per_thread *kpt) { long nevents; struct timespec expire_at; + if (kpt->nchanges) + changelist_prepare(kpt->events, kpt->changelist); + if (kpt->ts) { clock_gettime(CLOCK_MONOTONIC, &expire_at); expire_at.tv_sec += kpt->ts->tv_sec; expire_at.tv_nsec += kpt->ts->tv_nsec; @@ -331,11 +334,11 @@ * If event retrieval is desired, a block taking 6-elements (one for each * field of the kevent struct) must be passed. */ static VALUE sp_kevent(int argc, VALUE *argv, VALUE self) { - struct timespec ts; + struct timespec ts, *t; VALUE changelist, events, timeout; struct kq_per_thread *kpt; int nchanges, nevents; rb_scan_args(argc, argv, "03", &changelist, &events, &timeout); @@ -360,16 +363,18 @@ rb_raise(rb_eArgError, "nevents specified but block not given"); nevents = 0; } - kpt = kpt_get(self, nchanges, nevents); - kpt->ts = NIL_P(timeout) ? NULL : value2timespec(&ts, timeout); - if (nchanges) - changelist_prepare(kpt->events, changelist); + t = NIL_P(timeout) ? NULL : value2timespec(&ts, timeout); + kpt = kpt_get(nchanges, nevents); + kpt->ts = t; + kpt->changelist = changelist; + kpt->io = self; + kpt->fd = rb_sp_fileno(kpt->io); - return do_kevent(kpt); + return rb_ensure(do_kevent, (VALUE)kpt, rb_sp_puttlsbuf, (VALUE)kpt); } /* initialize constants in the SleepyPenguin::Ev namespace */ static void init_ev(VALUE mSleepyPenguin) { @@ -649,15 +654,11 @@ rb_define_method(cKqueue_IO, "kevent", sp_kevent, -1); id_for_fd = rb_intern("for_fd"); - if (RB_SP_GREEN_THREAD) - rb_require("sleepy_penguin/kqueue/io"); - - /* the high-level interface is implemented in Ruby: */ - rb_require("sleepy_penguin/kqueue"); - - /* Kevent helper struct */ - rb_require("sleepy_penguin/kevent"); + /* + * the high-level interface is implemented in Ruby + * see lib/sleepy_penguin/kevent.rb + */ } #endif /* HAVE_SYS_EVENT_H */