From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: AS47066 71.19.144.0/20 X-Spam-Status: No, score=-1.9 required=3.0 tests=AWL,BAYES_00 shortcircuit=no autolearn=unavailable version=3.3.2 X-Original-To: normalperson@yhbt.net Received: from zedshaw2.xen.prgmr.com (zedshaw2.xen.prgmr.com [71.19.156.177]) by dcvr.yhbt.net (Postfix) with ESMTP id F10AE1F6D2 for ; Tue, 30 Apr 2013 02:40:12 +0000 (UTC) Received: from zedshaw2.xen.prgmr.com (unknown [IPv6:::1]) by zedshaw2.xen.prgmr.com (Postfix) with ESMTP id 6FEAB73DEE for ; Tue, 30 Apr 2013 02:42:10 +0000 (UTC) MIME-Version: 1.0 Date: Tue, 30 Apr 2013 02:39:38 +0000 From: Eric Wong List-Archive: List-Help: List-Id: List-Post: List-Subscribe: List-Unsubscribe: Message-Id: <1367289582-31293-14-git-send-email-normalperson@yhbt.net> Precedence: list References: <1367289582-31293-1-git-send-email-normalperson@yhbt.net> Sender: sleepy.penguin@librelist.org Subject: [sleepy.penguin] [PATCH 13/17] kqueue: workaround lack of RSTRUCT* macros on Rubinius To: sleepy.penguin@librelist.org Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Rubinius will not support RSTRUCT* macros, so converting the structs to arrays is the least intrusive way to go about our code. ref: https://github.com/rubinius/rubinius/issues/494 --- ext/sleepy_penguin/kqueue.c | 70 ++++++++++++++++++++++++++++++++------------- test/test_kqueue_io.rb | 6 ++++ 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/ext/sleepy_penguin/kqueue.c b/ext/sleepy_penguin/kqueue.c index 78a13c3..155204b 100644 --- a/ext/sleepy_penguin/kqueue.c +++ b/ext/sleepy_penguin/kqueue.c @@ -24,6 +24,18 @@ # define NUM2USHORT(n) (short)NUM2UINT(n) #endif +/* + * Rubinius does not support RSTRUCT_* in the C API: + * ref: https://github.com/rubinius/rubinius/issues/494 + */ +#if defined(RUBINIUS) +# define RBX_STRUCT (1) +# define RSTRUCT_LEN(s) 0, rb_bug("RSTRUCT_LEN attempted in Rubinius") +# define RSTRUCT_PTR(s) NULL, rb_bug("RSTRUCT_PTR attempted in Rubinius") +#else +# define RBX_STRUCT (0) +#endif + static const long NANO_PER_SEC = 1000000000; static ID id_for_fd; static VALUE mEv, mEvFilt, mNote, mVQ; @@ -233,33 +245,42 @@ static void event_set(struct kevent *event, VALUE *chg) EV_SET(event, ident, filter, flags, fflags, data, udata); } +/* sets ptr and len */ +static void unpack_event(VALUE **ptr, VALUE *len, VALUE *event) +{ + switch (TYPE(*event)) { + case T_STRUCT: + if (RBX_STRUCT) { + *event = rb_funcall(*event, rb_intern("to_a"), 0, 0); + /* fall-through to T_ARRAY */ + } else { + *len = RSTRUCT_LEN(*event); + *ptr = RSTRUCT_PTR(*event); + return; + } + case T_ARRAY: + *len = RARRAY_LEN(*event); + *ptr = RARRAY_PTR(*event); + return; + default: + rb_raise(rb_eTypeError, "unsupported type in changelist"); + } +} + static void ary2eventlist(struct kevent *events, VALUE changelist) { VALUE *chg = RARRAY_PTR(changelist); long i = RARRAY_LEN(changelist); + VALUE event; for (; --i >= 0; chg++) { VALUE clen; VALUE *cptr; - switch (TYPE(*chg)) { - case T_STRUCT: - clen = RSTRUCT_LEN(*chg); - cptr = RSTRUCT_PTR(*chg); - break; - case T_ARRAY: - clen = RARRAY_LEN(*chg); - cptr = RARRAY_PTR(*chg); - break; - default: - rb_raise(rb_eTypeError, - "unsupported type in changelist"); - } - if (clen != 6) { - fprintf(stderr, "clen: %ld\n", clen); - rb_p(*chg); + event = *chg; + unpack_event(&cptr, &clen, &event); + if (clen != 6) goto out_list; - } event_set(events++, cptr); } return; @@ -273,14 +294,23 @@ 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); - break; + return; case T_STRUCT: - if (RSTRUCT_LEN(changelist) != 6) + event = changelist; + unpack_event(&cptr, &clen, &event); + if (clen != 6) rb_raise(rb_eTypeError, "event is not a Kevent struct"); - event_set(events, RSTRUCT_PTR(changelist)); + event_set(events, cptr); + return; + default: + rb_bug("changelist_prepare not type filtered by sp_kevent"); } } diff --git a/test/test_kqueue_io.rb b/test/test_kqueue_io.rb index 904a1cc..076c9f0 100644 --- a/test/test_kqueue_io.rb +++ b/test/test_kqueue_io.rb @@ -16,6 +16,12 @@ def teardown end end + def test_bad_type + kq = Kqueue::IO.new + @to_close << kq + assert_raises(TypeError) { kq.kevent("HI") } + end + def test_multi_event kq = Kqueue::IO.new @to_close << kq -- 1.8.2.1.367.gc875ca7