summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--thread.c12
-rw-r--r--thread_win32.c28
-rw-r--r--win32/win32.c21
4 files changed, 72 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 50c8391ebf..924451260d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Thu Jun 16 03:00:26 2011 NAKAMURA Usaku <usa@ruby-lang.org>
+
+ * thread.c (do_select): Windows: no need to poll if select(2) is
+ cancelable.
+
+ * thread_win32.c (native_fd_select): new function to make select(2)
+ cancelable.
+
+ * thread_win32.c (rb_w32_check_interrupt): new function for checking
+ interrupt.
+
+ * win32/win32.c (rb_w32_select_with_thread): new function. cancelable
+ select(2).
+
+ * win32/win32.c (rb_w32_select): use above function internally.
+
Wed Jun 15 23:30:45 2011 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* gc.c: fix a regression by r31690 on AIX because AIX malloc
diff --git a/thread.c b/thread.c
index 208c4be074..230e333a40 100644
--- a/thread.c
+++ b/thread.c
@@ -2537,7 +2537,7 @@ do_select(int n, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except,
# endif
if (timeout) {
-# if defined(__CYGWIN__) || defined(_WIN32)
+# if defined(__CYGWIN__)
gettimeofday(&start_time, NULL);
limit = (double)start_time.tv_sec + (double)start_time.tv_usec*1e-6;
# else
@@ -2558,7 +2558,7 @@ do_select(int n, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except,
retry:
lerrno = 0;
-#if defined(__CYGWIN__) || defined(_WIN32)
+#if defined(__CYGWIN__)
{
int finish = 0;
/* polling duration: 100ms */
@@ -2595,6 +2595,14 @@ do_select(int n, rb_fdset_t *read, rb_fdset_t *write, rb_fdset_t *except,
}, 0, 0);
} while (result == 0 && !finish);
}
+#elif defined(_WIN32)
+ {
+ rb_thread_t *th = GET_THREAD();
+ BLOCKING_REGION({
+ result = native_fd_select(n, read, write, except, timeout, th);
+ if (result < 0) lerrno = errno;
+ }, ubf_select, th);
+ }
#else
BLOCKING_REGION({
result = rb_fd_select(n, read, write, except, timeout);
diff --git a/thread_win32.c b/thread_win32.c
index 668d94b6c7..172c942033 100644
--- a/thread_win32.c
+++ b/thread_win32.c
@@ -673,6 +673,34 @@ native_thread_apply_priority(rb_thread_t *th)
#endif /* USE_NATIVE_THREAD_PRIORITY */
+int rb_w32_select_with_thread(int, fd_set *, fd_set *, fd_set *, struct timeval *, void *); /* @internal */
+
+static int
+native_fd_select(int n, rb_fdset_t *readfds, rb_fdset_t *writefds, rb_fdset_t *exceptfds, struct timeval *timeout, rb_thread_t *th)
+{
+ fd_set *r = NULL, *w = NULL, *e = NULL;
+ if (readfds) {
+ rb_fd_resize(n - 1, readfds);
+ r = rb_fd_ptr(readfds);
+ }
+ if (writefds) {
+ rb_fd_resize(n - 1, writefds);
+ w = rb_fd_ptr(writefds);
+ }
+ if (exceptfds) {
+ rb_fd_resize(n - 1, exceptfds);
+ e = rb_fd_ptr(exceptfds);
+ }
+ return rb_w32_select_with_thread(n, r, w, e, timeout, th);
+}
+
+/* @internal */
+int
+rb_w32_check_interrupt(rb_thread_t *th)
+{
+ return w32_wait_events(0, 0, 0, th);
+}
+
static void
ubf_handle(void *ptr)
{
diff --git a/win32/win32.c b/win32/win32.c
index d636b74e2d..b3ffcffa07 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -2591,9 +2591,13 @@ compare(const struct timeval *t1, const struct timeval *t2)
}
#undef Sleep
-int WSAAPI
-rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
- struct timeval *timeout)
+
+int rb_w32_check_interrupt(void *); /* @internal */
+
+/* @internal */
+int
+rb_w32_select_with_thread(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
+ struct timeval *timeout, void *th)
{
int r;
rb_fdset_t pipe_rd;
@@ -2672,6 +2676,10 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
wait.tv_sec = 0; wait.tv_usec = 10 * 1000; // 10ms
zero.tv_sec = 0; zero.tv_usec = 0; // 0ms
for (;;) {
+ if (th && rb_w32_check_interrupt(th) != WAIT_TIMEOUT) {
+ r = -1;
+ break;
+ }
if (nonsock) {
// modifying {else,pipe,cons}_rd is safe because
// if they are modified, function returns immediately.
@@ -2724,6 +2732,13 @@ rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
return r;
}
+int WSAAPI
+rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
+ struct timeval *timeout)
+{
+ return rb_w32_select_with_thread(nfds, rd, wr, ex, timeout, 0);
+}
+
static FARPROC
get_wsa_extension_function(SOCKET s, GUID *guid)
{