summaryrefslogtreecommitdiff
path: root/thread.c
diff options
context:
space:
mode:
authorkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-04 00:59:57 +0000
committerkosaki <kosaki@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2011-05-04 00:59:57 +0000
commit9be37ca7d51513658f5f84d98fa5e46026cc5a04 (patch)
tree5f1528e2a327b9d98b335fc2f599751a16c8c704 /thread.c
parentd47073de04f706c9d044b0fad694e5936dabc207 (diff)
* 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] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@31419 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'thread.c')
-rw-r--r--thread.c89
1 files changed, 77 insertions, 12 deletions
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