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 */