summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--include/ruby/io.h5
-rw-r--r--io.c42
-rw-r--r--thread.c89
4 files changed, 101 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index e23b394945..a470c2b4c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+Wed May 4 09:56:57 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * 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@tenderlovemaking.com>
* ext/psych/lib/psych/visitors/yaml_tree.rb: fix time dumping so that
diff --git a/include/ruby/io.h b/include/ruby/io.h
index 13f42591bd..bf1b9f8b37 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -27,6 +27,10 @@ extern "C" {
#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_get_write_io(VALUE io);
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);
diff --git a/io.c b/io.c
index 1278e7fa5b..425ef8083a 100644
--- a/io.c
+++ b/io.c
@@ -685,21 +685,9 @@ io_fflush(rb_io_t *fptr)
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 @@ rb_io_wait_readable(int f)
#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 @@ rb_io_wait_readable(int f)
}
}
-#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 @@ rb_io_wait_writable(int f)
#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:
diff --git a/thread.c b/thread.c
index 486a5a2b6c..8d681f7f41 100644
--- a/thread.c
+++ b/thread.c
@@ -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 @@ static void
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,18 +2628,7 @@ rb_thread_wait_fd_rw(int fd, int read)
}
if (rb_thread_alone()) return;
while (result <= 0) {
- rb_fdset_t set;
- rb_fd_init(&set);
- FD_SET(fd, &set);
-
- 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);
+ result = rb_wait_for_single_fd(fd, events, NULL);
if (result < 0) {
rb_sys_fail(0);
@@ -2712,6 +2704,79 @@ rb_thread_fd_select(int max, rb_fdset_t * read, rb_fdset_t * write, rb_fdset_t *
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