sleepy_penguin RubyGem user+dev discussion/patches/pulls/bugs/help
 help / color / Atom feed
From: Eric Wong <e@80x24.org>
To: sleepy-penguin@bogomips.org
Subject: [PATCH] kqueue: modernize Struct usage for Ruby 2.5.0dev
Date: Sat, 15 Apr 2017 00:25:01 +0000
Message-ID: <20170415002501.19627-1-e@80x24.org> (raw)

Ruby 2.4 deprecates old macros, and it looks like 2.5.0 will
remove RSTRUCT_PTR.
---
 ext/sleepy_penguin/extconf.rb |   1 +
 ext/sleepy_penguin/kqueue.c   | 115 ++++++++++++++++++++++++++----------------
 2 files changed, 73 insertions(+), 43 deletions(-)

diff --git a/ext/sleepy_penguin/extconf.rb b/ext/sleepy_penguin/extconf.rb
index e07f5d2..f11f9c1 100644
--- a/ext/sleepy_penguin/extconf.rb
+++ b/ext/sleepy_penguin/extconf.rb
@@ -34,4 +34,5 @@ have_func('rb_thread_fd_close')
 have_func('rb_update_max_fd')
 have_func('rb_fd_fix_cloexec')
 have_func('rb_io_get_io')
+have_func('rb_struct_size')
 create_makefile('sleepy_penguin_ext')
diff --git a/ext/sleepy_penguin/kqueue.c b/ext/sleepy_penguin/kqueue.c
index d7e8d8e..e6c133f 100644
--- a/ext/sleepy_penguin/kqueue.c
+++ b/ext/sleepy_penguin/kqueue.c
@@ -18,6 +18,9 @@
 #ifndef RARRAY_LENINT
 #  define RARRAY_LENINT(ary) (int)RARRAY_LEN(ary)
 #endif
+#ifndef RARRAY_CONST_PTR
+#  define RARRAY_CONST_PTR(ary) RARRAY_PTR(ary)
+#endif
 #ifndef NUM2SHORT
 #  define NUM2SHORT(n) (short)NUM2INT(n)
 #endif
@@ -233,35 +236,82 @@ static VALUE do_kevent(struct kq_per_thread *kpt)
 	return kevent_result(kpt, (int)nevents);
 }
 
-static void event_set(struct kevent *event, VALUE *chg)
+#if defined(HAVE_RB_STRUCT_SIZE) && defined(RSTRUCT_GET)
+static void ev_set_struct(struct kevent *ev, VALUE event)
 {
-	uintptr_t ident = (uintptr_t)NUM2ULONG(chg[0]);
-	short filter = NUM2SHORT(chg[1]);
-	unsigned short flags = NUM2USHORT(chg[2]);
-	unsigned fflags = (unsigned)NUM2UINT(chg[3]);
-	intptr_t data = (intptr_t)NUM2LONG(chg[4]);
-	void *udata = (void *)chg[5];
-
-	EV_SET(event, ident, filter, flags, fflags, data, udata);
+	if (rb_struct_size(event) == INT2NUM(6)) {
+		uintptr_t ident = (uintptr_t)NUM2ULONG(RSTRUCT_GET(event, 0));
+		short filter = NUM2SHORT(RSTRUCT_GET(event, 1));
+		unsigned short flags = NUM2USHORT(RSTRUCT_GET(event, 2));
+		unsigned fflags = (unsigned)NUM2UINT(RSTRUCT_GET(event, 3));
+		intptr_t data = (intptr_t)NUM2LONG(RSTRUCT_GET(event, 4));
+		void *udata = (void *)RSTRUCT_GET(event, 5);
+
+		EV_SET(ev, ident, filter, flags, fflags, data, udata);
+	} else {
+		rb_raise(rb_eTypeError, "unsupported struct in changelist");
+	}
+}
+#elif RBX_STRUCT == 0 && defined(RSTRUCT_LEN) && defined(RSTRUCT_PTR)
+/* legacy MRI */
+static void ev_set_struct(struct kevent *ev, VALUE event)
+{
+	long len = RSTRUCT_LEN(*event);
+	if (len == 6) {
+		const VALUE *ptr = RSTRUCT_PTR(*event);
+		uintptr_t ident = (uintptr_t)NUM2ULONG(ptr[0]);
+		short filter = NUM2SHORT(ptr[1]);
+		unsigned short flags = NUM2USHORT(ptr[2]);
+		unsigned fflags = (unsigned)NUM2UINT(ptr[3]);
+		intptr_t data = (intptr_t)NUM2LONG(ptr[4]);
+		void *udata = (void *)ptr[5];
+
+		EV_SET(event, ident, filter, flags, fflags, data, udata);
+	} else {
+		rb_raise(rb_eTypeError, "unsupported struct in changelist");
+	}
+}
+#else
+static void ev_set_struct(struct kevent *ev, VALUE event)
+{
+	rb_raise(rb_eTypeError, "unsupported struct in changelist");
+}
+#endif
+
+static void ev_set_ary(struct kevent *ev, VALUE event)
+{
+	long len = RARRAY_LEN(event);
+	const VALUE *ptr = RARRAY_CONST_PTR(event);
+
+	if (len == 6) {
+		uintptr_t ident = (uintptr_t)NUM2ULONG(ptr[0]);
+		short filter = NUM2SHORT(ptr[1]);
+		unsigned short flags = NUM2USHORT(ptr[2]);
+		unsigned fflags = (unsigned)NUM2UINT(ptr[3]);
+		intptr_t data = (intptr_t)NUM2LONG(ptr[4]);
+		void *udata = (void *)ptr[5];
+
+		EV_SET(ev, ident, filter, flags, fflags, data, udata);
+		return;
+	}
+	rb_raise(rb_eTypeError,
+		"changelist must be an array of 6-element arrays or structs");
 }
 
 /* sets ptr and len */
-static void unpack_event(VALUE **ptr, VALUE *len, VALUE *event)
+static void unpack_event(struct kevent *ev, VALUE event)
 {
-	switch (TYPE(*event)) {
+	switch (TYPE(event)) {
 	case T_STRUCT:
 		if (RBX_STRUCT) {
-			*event = rb_funcall(*event, rb_intern("to_a"), 0, 0);
+			event = rb_funcall(event, rb_intern("to_a"), 0, 0);
 			/* fall-through to T_ARRAY */
 		} else {
-			*len = RSTRUCT_LEN(*event);
-			*ptr = RSTRUCT_PTR(*event);
+			ev_set_struct(ev, event);
 			return;
 		}
 	case T_ARRAY:
-		*len = RARRAY_LEN(*event);
-		*ptr = RARRAY_PTR(*event);
-		return;
+		ev_set_ary(ev, event);
 	default:
 		rb_raise(rb_eTypeError, "unsupported type in changelist");
 	}
@@ -269,24 +319,11 @@ static void unpack_event(VALUE **ptr, VALUE *len, VALUE *event)
 
 static void ary2eventlist(struct kevent *events, VALUE changelist)
 {
-	VALUE *chg = RARRAY_PTR(changelist);
+	const VALUE *chg = RARRAY_CONST_PTR(changelist);
 	long i = RARRAY_LEN(changelist);
-	VALUE event;
 
-	for (; --i >= 0; chg++) {
-		VALUE clen;
-		VALUE *cptr;
-
-		event = *chg;
-		unpack_event(&cptr, &clen, &event);
-		if (clen != 6)
-			goto out_list;
-		event_set(events++, cptr);
-	}
-	return;
-out_list:
-	rb_raise(rb_eTypeError,
-		"changelist must be an array of 6-element arrays or structs");
+	for (; --i >= 0; chg++)
+		unpack_event(events++, *chg);
 }
 
 /*
@@ -294,20 +331,12 @@ out_list:
  */
 static void changelist_prepare(struct kevent *events, VALUE changelist)
 {
-	VALUE *cptr;
-	VALUE clen;
-	VALUE event;
-
 	switch (TYPE(changelist)) {
 	case T_ARRAY:
 		ary2eventlist(events, changelist);
 		return;
-	case T_STRUCT:
-		event = changelist;
-		unpack_event(&cptr, &clen, &event);
-		if (clen != 6)
-			rb_raise(rb_eTypeError, "event is not a Kevent struct");
-		event_set(events, cptr);
+	case T_STRUCT: /* single event */
+		unpack_event(events, changelist);
 		return;
 	default:
 		rb_bug("changelist_prepare not type filtered by sp_kevent");
-- 
EW


                 reply index

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publically to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://bogomips.org/sleepy_penguin/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170415002501.19627-1-e@80x24.org \
    --to=e@80x24.org \
    --cc=sleepy-penguin@bogomips.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

sleepy_penguin RubyGem user+dev discussion/patches/pulls/bugs/help

Archives are clonable:
	git clone --mirror https://bogomips.org/sleepy-penguin
	git clone --mirror http://ou63pmih66umazou.onion/sleepy-penguin

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.lang.ruby.sleepy-penguin
	nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.sleepy-penguin

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/ public-inbox