about summary refs log tree commit homepage
path: root/ext/sleepy_penguin/kqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sleepy_penguin/kqueue.c')
-rw-r--r--ext/sleepy_penguin/kqueue.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/ext/sleepy_penguin/kqueue.c b/ext/sleepy_penguin/kqueue.c
index 22e20f1..22a2c5d 100644
--- a/ext/sleepy_penguin/kqueue.c
+++ b/ext/sleepy_penguin/kqueue.c
@@ -43,6 +43,7 @@ static VALUE mEv, mEvFilt, mNote, mVQ;
 
 struct kq_per_thread {
         VALUE io;
+        VALUE changelist;
         int fd;
         int nchanges;
         int nevents;
@@ -72,7 +73,7 @@ static int kq_fd_check(struct kq_per_thread *kpt)
         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;
@@ -89,8 +90,6 @@ static struct kq_per_thread *kpt_get(VALUE self, int nchanges, int nevents)
         kpt->capa = max;
         kpt->nchanges = nchanges;
         kpt->nevents = nevents;
-        kpt->io = self;
-        kpt->fd = rb_sp_fileno(kpt->io);
 
         return kpt;
 }
@@ -203,11 +202,16 @@ static VALUE nogvl_kevent(void *args)
         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);
 
@@ -333,7 +337,7 @@ static void changelist_prepare(struct kevent *events, VALUE changelist)
  */
 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;
@@ -362,12 +366,14 @@ static VALUE sp_kevent(int argc, VALUE *argv, VALUE self)
                 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 */