[前][次][番号順一覧][スレッド一覧]

ruby-changes:19379

From: kosaki <ko1@a...>
Date: Wed, 4 May 2011 10:00:06 +0900 (JST)
Subject: [ruby-changes:19379] Ruby:r31419 (trunk): * thread.c (rb_wait_for_single_fd): new.

kosaki	2011-05-04 09:59:57 +0900 (Wed, 04 May 2011)

  New Revision: 31419

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=31419

  Log:
    * thread.c (rb_wait_for_single_fd): new.
    * thread.c (select_single): select(2) based backend for rb_wait_for_single_fd().
    
    * io.c (make_writeconv): use rb_wait_for_single_fd() instaed of
      rb_thread_fd_select().
    * io.c (rb_io_wait_readable): ditto.
    * thread.c (rb_thread_wait_fd_rw): ditto.
    
    * io.c (wait_readable): removed.
    * thread.c (init_set_fd): new helper function.
    * include/ruby/io.h (RB_WAITFD_IN, RB_WAITFD_PRI, RB_WAITFD_OUT):
      new constant for rb_single_wait_fd().
    
    The patch was written by Eric Wong. [Ruby 1.9 - Feature #4531]

  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/io.h
    trunk/io.c
    trunk/thread.c

Index: include/ruby/io.h
===================================================================
--- include/ruby/io.h	(revision 31418)
+++ include/ruby/io.h	(revision 31419)
@@ -27,6 +27,10 @@
 #include <stdio_ext.h>
 #endif
 
+#define RB_WAITFD_IN  0x001
+#define RB_WAITFD_PRI 0x002
+#define RB_WAITFD_OUT 0x004
+
 #if defined __GNUC__ && __GNUC__ >= 4
 #pragma GCC visibility push(default)
 #endif
@@ -160,6 +164,7 @@
 VALUE rb_io_set_write_io(VALUE io, VALUE w);
 int rb_io_wait_readable(int);
 int rb_io_wait_writable(int);
+int rb_wait_for_single_fd(int fd, int events, struct timeval *tv);
 void rb_io_set_nonblock(rb_io_t *fptr);
 int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p);
 ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 31418)
+++ ChangeLog	(revision 31419)
@@ -1,3 +1,20 @@
+Wed May  4 09:56:57 2011  KOSAKI Motohiro  <kosaki.motohiro@g...>
+
+	* thread.c (rb_wait_for_single_fd): new.
+	* thread.c (select_single): select(2) based backend for rb_wait_for_single_fd().
+
+	* io.c (make_writeconv): use rb_wait_for_single_fd() instaed of
+	  rb_thread_fd_select().
+	* io.c (rb_io_wait_readable): ditto.
+	* thread.c (rb_thread_wait_fd_rw): ditto.
+
+	* io.c (wait_readable): removed.
+	* thread.c (init_set_fd): new helper function.
+	* include/ruby/io.h (RB_WAITFD_IN, RB_WAITFD_PRI, RB_WAITFD_OUT):
+	  new constant for rb_single_wait_fd().
+
+	The patch was written by Eric Wong. [Ruby 1.9 - Feature #4531]
+
 Wed May  4 08:04:59 2011  Aaron Patterson <aaron@t...>
 
 	* ext/psych/lib/psych/visitors/yaml_tree.rb: fix time dumping so that
Index: io.c
===================================================================
--- io.c	(revision 31418)
+++ io.c	(revision 31419)
@@ -685,21 +685,9 @@
     return 0;
 }
 
-#ifdef HAVE_RB_FD_INIT
-static VALUE
-wait_readable(VALUE p)
-{
-    rb_fdset_t *rfds = (rb_fdset_t *)p;
-
-    return rb_thread_fd_select(rb_fd_max(rfds), rfds, NULL, NULL, NULL);
-}
-#endif
-
 int
 rb_io_wait_readable(int f)
 {
-    rb_fdset_t rfds;
-
     if (f < 0) {
 	rb_raise(rb_eIOError, "closed stream");
     }
@@ -715,14 +703,7 @@
 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
       case EWOULDBLOCK:
 #endif
-	rb_fd_init(&rfds);
-	rb_fd_set(f, &rfds);
-#ifdef HAVE_RB_FD_INIT
-	rb_ensure(wait_readable, (VALUE)&rfds,
-		  (VALUE (*)(VALUE))rb_fd_term, (VALUE)&rfds);
-#else
-	rb_thread_fd_select(f + 1, &rfds, NULL, NULL, NULL);
-#endif
+	rb_wait_for_single_fd(f, RB_WAITFD_IN, NULL);
 	return TRUE;
 
       default:
@@ -730,21 +711,9 @@
     }
 }
 
-#ifdef HAVE_RB_FD_INIT
-static VALUE
-wait_writable(VALUE p)
-{
-    rb_fdset_t *wfds = (rb_fdset_t *)p;
-
-    return rb_thread_fd_select(rb_fd_max(wfds), NULL, wfds, NULL, NULL);
-}
-#endif
-
 int
 rb_io_wait_writable(int f)
 {
-    rb_fdset_t wfds;
-
     if (f < 0) {
 	rb_raise(rb_eIOError, "closed stream");
     }
@@ -760,14 +729,7 @@
 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
       case EWOULDBLOCK:
 #endif
-	rb_fd_init(&wfds);
-	rb_fd_set(f, &wfds);
-#ifdef HAVE_RB_FD_INIT
-	rb_ensure(wait_writable, (VALUE)&wfds,
-		  (VALUE (*)(VALUE))rb_fd_term, (VALUE)&wfds);
-#else
-	rb_thread_fd_select(f + 1, NULL, &wfds, NULL, NULL);
-#endif
+	rb_wait_for_single_fd(f, RB_WAITFD_OUT, NULL);
 	return TRUE;
 
       default:
Index: thread.c
===================================================================
--- thread.c	(revision 31418)
+++ thread.c	(revision 31419)
@@ -46,6 +46,7 @@
 
 #include "eval_intern.h"
 #include "gc.h"
+#include "ruby/io.h"
 
 #ifndef USE_NATIVE_THREAD_PRIORITY
 #define USE_NATIVE_THREAD_PRIORITY 0
@@ -2618,6 +2619,8 @@
 rb_thread_wait_fd_rw(int fd, int read)
 {
     int result = 0;
+    int events = read ? RB_WAITFD_IN : RB_WAITFD_OUT;
+
     thread_debug("rb_thread_wait_fd_rw(%d, %s)\n", fd, read ? "read" : "write");
 
     if (fd < 0) {
@@ -2625,19 +2628,8 @@
     }
     if (rb_thread_alone()) return;
     while (result <= 0) {
-	rb_fdset_t set;
-	rb_fd_init(&set);
-	FD_SET(fd, &set);
+	result = rb_wait_for_single_fd(fd, events, NULL);
 
-	if (read) {
-	    result = do_select(fd + 1, &set, 0, 0, 0);
-	}
-	else {
-	    result = do_select(fd + 1, 0, &set, 0, 0);
-	}
-
-	rb_fd_term(&set);
-
 	if (result < 0) {
 	    rb_sys_fail(0);
 	}
@@ -2712,7 +2704,80 @@
     return do_select(max, read, write, except, timeout);
 }
 
+static rb_fdset_t *init_set_fd(int fd, rb_fdset_t *fds)
+{
+    rb_fd_init(fds);
+    rb_fd_set(fd, fds);
 
+    return fds;
+}
+
+struct select_args {
+    union {
+	int fd;
+	int error;
+    } as;
+    rb_fdset_t *read;
+    rb_fdset_t *write;
+    rb_fdset_t *except;
+    struct timeval *tv;
+};
+
+static VALUE
+select_single(VALUE ptr)
+{
+    struct select_args *args = (struct select_args *)ptr;
+    int r;
+
+    r = rb_thread_fd_select(args->as.fd + 1,
+                            args->read, args->write, args->except, args->tv);
+    if (r == -1)
+	args->as.error = errno;
+    if (r > 0) {
+	r = 0;
+	if (args->read && rb_fd_isset(args->as.fd, args->read))
+	    r |= RB_WAITFD_IN;
+	if (args->write && rb_fd_isset(args->as.fd, args->write))
+	    r |= RB_WAITFD_OUT;
+	if (args->except && rb_fd_isset(args->as.fd, args->except))
+	    r |= RB_WAITFD_PRI;
+    }
+    return (VALUE)r;
+}
+
+static VALUE
+select_single_cleanup(VALUE ptr)
+{
+    struct select_args *args = (struct select_args *)ptr;
+
+    if (args->read) rb_fd_term(args->read);
+    if (args->write) rb_fd_term(args->write);
+    if (args->except) rb_fd_term(args->except);
+
+    return (VALUE)-1;
+}
+
+int
+rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
+{
+    rb_fdset_t rfds, wfds, efds;
+    struct select_args args;
+    int r;
+    VALUE ptr = (VALUE)&args;
+
+    args.as.fd = fd;
+    args.read = (events & RB_WAITFD_IN) ? init_set_fd(fd, &rfds) : NULL;
+    args.write = (events & RB_WAITFD_OUT) ? init_set_fd(fd, &wfds) : NULL;
+    args.except = (events & RB_WAITFD_PRI) ? init_set_fd(fd, &efds) : NULL;
+    args.tv = tv;
+
+    r = (int)rb_ensure(select_single, ptr, select_single_cleanup, ptr);
+    if (r == -1)
+	errno = args.as.error;
+
+    return r;
+}
+
 /*
  * for GC
  */

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]