ruby-changes:6748
From: nobu <ko1@a...>
Date: Wed, 30 Jul 2008 17:49:02 +0900 (JST)
Subject: [ruby-changes:6748] Ruby:r18262 (trunk, ruby_1_8): * win32/win32.c (rb_w32_select): recalc the rest of timeout for each
nobu 2008-07-30 17:48:31 +0900 (Wed, 30 Jul 2008) New Revision: 18262 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=18262 Log: * win32/win32.c (rb_w32_select): recalc the rest of timeout for each iterations. [ruby-core:18015] Added files: branches/ruby_1_8/test/ruby/test_sleep.rb trunk/test/ruby/test_sleep.rb Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/win32/win32.c trunk/ChangeLog trunk/thread.c trunk/win32/win32.c Index: ChangeLog =================================================================== --- ChangeLog (revision 18261) +++ ChangeLog (revision 18262) @@ -1,3 +1,8 @@ +Wed Jul 30 17:48:15 2008 Nobuyoshi Nakada <nobu@r...> + + * win32/win32.c (rb_w32_select): recalc the rest of timeout for each + iterations. [ruby-core:18015] + Tue Jul 29 23:37:37 2008 Yusuke Endoh <mame@t...> * io.c (io_ungetc): raise NotImplementedError when ungetc is called Index: thread.c =================================================================== --- thread.c (revision 18261) +++ thread.c (revision 18262) @@ -1957,7 +1957,7 @@ } static int -subst(struct timeval *rest, const struct timeval *wait) +subtract_tv(struct timeval *rest, const struct timeval *wait) { while (rest->tv_usec < wait->tv_usec) { if (rest->tv_sec <= wait->tv_sec) { @@ -1982,10 +1982,18 @@ #ifndef linux double limit = 0; struct timeval wait_rest; +# if defined(__CYGWIN__) || defined(_WIN32) + struct timeval start_time; +# endif if (timeout) { - limit = timeofday() + - (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6; +# if defined(__CYGWIN__) || defined(_WIN32) + gettimeofday(&start_time, NULL); + limit = (double)start_time.tv_sec + (double)start_time.tv_usec*1e-6; +# else + limit = timeofday(); +# endif + limit += (double)timeout->tv_sec+(double)timeout->tv_usec*1e-6; wait_rest = *timeout; timeout = &wait_rest; } @@ -2000,6 +2008,7 @@ #if defined(__CYGWIN__) || defined(_WIN32) { + int finish = 0; /* polling duration: 100ms */ struct timeval wait_100ms, *wait; wait_100ms.tv_sec = 0; @@ -2017,9 +2026,19 @@ if (write) *write = orig_write; if (except) *except = orig_except; wait = &wait_100ms; - } while (__th->interrupt_flag == 0 && (timeout == 0 || subst(timeout, &wait_100ms))); + if (timeout) { + struct timeval elapsed; + gettimeofday(&elapsed, NULL); + subtract_tv(&elapsed, &start_time); + if (!subtract_tv(timeout, &elapsed)) { + finish = 1; + break; + } + if (cmp_tv(&wait_100ms, timeout) < 0) wait = timeout; + } + } while (__th->interrupt_flag == 0); }, 0, 0); - } while (result == 0 && (timeout == 0 || subst(timeout, &wait_100ms))); + } while (result == 0 && !finish); } #else BLOCKING_REGION({ Index: win32/win32.c =================================================================== --- win32/win32.c (revision 18261) +++ win32/win32.c (revision 18262) @@ -2143,7 +2143,7 @@ } static inline int -subst(struct timeval *rest, const struct timeval *wait) +subtract(struct timeval *rest, const struct timeval *wait) { while (rest->tv_usec < wait->tv_usec) { if (rest->tv_sec <= wait->tv_sec) { @@ -2174,7 +2174,7 @@ #undef Sleep int WSAAPI rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, - struct timeval *timeout) + struct timeval *timeout) { int r; fd_set pipe_rd; @@ -2183,11 +2183,29 @@ fd_set else_wr; fd_set except; int nonsock = 0; + struct timeval limit; if (nfds < 0 || (timeout && (timeout->tv_sec < 0 || timeout->tv_usec < 0))) { errno = EINVAL; return -1; } + + if (timeout) { + if (timeout->tv_sec < 0 || + timeout->tv_usec < 0 || + timeout->tv_usec >= 1000000) { + errno = EINVAL; + return -1; + } + gettimeofday(&limit, NULL); + limit.tv_sec += timeout->tv_sec; + limit.tv_usec += timeout->tv_usec; + if (limit.tv_usec >= 1000000) { + limit.tv_usec -= 1000000; + limit.tv_sec++; + } + } + if (!NtSocketsInitialized) { StartSockets(); } @@ -2223,10 +2241,9 @@ struct timeval rest; struct timeval wait; struct timeval zero; - if (timeout) rest = *timeout; wait.tv_sec = 0; wait.tv_usec = 10 * 1000; // 10ms zero.tv_sec = 0; zero.tv_usec = 0; // 0ms - do { + for (;;) { if (nonsock) { // modifying {else,pipe,cons}_rd is safe because // if they are modified, function returns immediately. @@ -2242,8 +2259,7 @@ break; } else { - struct timeval *dowait = - compare(&rest, &wait) < 0 ? &rest : &wait; + struct timeval *dowait = &wait; fd_set orig_rd; fd_set orig_wr; @@ -2257,10 +2273,16 @@ if (wr) *wr = orig_wr; if (ex) *ex = orig_ex; - // XXX: should check the time select spent + if (timeout) { + struct timeval now; + gettimeofday(&now, NULL); + rest = limit; + if (!subtract(&rest, &now)) break; + if (compare(&rest, &wait) < 0) dowait = &rest; + } Sleep(dowait->tv_sec * 1000 + dowait->tv_usec / 1000); } - } while (!timeout || subst(&rest, &wait)); + } } return r; Index: test/ruby/test_sleep.rb =================================================================== --- test/ruby/test_sleep.rb (revision 0) +++ test/ruby/test_sleep.rb (revision 18262) @@ -0,0 +1,10 @@ +require 'test/unit' + +class TestSleep < Test::Unit::TestCase + def test_sleep_5sec + start = Time.now + sleep 5 + slept = Time.now-start + assert_in_delta(5.0, slept, 0.1, "[ruby-core:18015]: longer than expected") + end +end Property changes on: test/ruby/test_sleep.rb ___________________________________________________________________ Name: svn:eol-style + LF Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 18261) +++ ruby_1_8/ChangeLog (revision 18262) @@ -1,3 +1,8 @@ +Wed Jul 30 17:48:15 2008 Nobuyoshi Nakada <nobu@r...> + + * win32/win32.c (rb_w32_select): recalc the rest of timeout for each + iterations. [ruby-core:18015] + Tue Jul 29 05:37:53 2008 Nobuyoshi Nakada <nobu@r...> * file.c (rb_find_file_ext, rb_find_file): explicit relative path Index: ruby_1_8/test/ruby/test_sleep.rb =================================================================== --- ruby_1_8/test/ruby/test_sleep.rb (revision 0) +++ ruby_1_8/test/ruby/test_sleep.rb (revision 18262) @@ -0,0 +1,10 @@ +require 'test/unit' + +class TestSleep < Test::Unit::TestCase + def test_sleep_5sec + start = Time.now + sleep 5 + slept = Time.now-start + assert_in_delta(5.0, slept, 0.1, "[ruby-core:18015]: longer than expected") + end +end Property changes on: ruby_1_8/test/ruby/test_sleep.rb ___________________________________________________________________ Name: svn:eol-style + LF Index: ruby_1_8/win32/win32.c =================================================================== --- ruby_1_8/win32/win32.c (revision 18261) +++ ruby_1_8/win32/win32.c (revision 18262) @@ -2177,7 +2177,7 @@ } static inline int -subst(struct timeval *rest, const struct timeval *wait) +subtract(struct timeval *rest, const struct timeval *wait) { while (rest->tv_usec < wait->tv_usec) { if (rest->tv_sec <= wait->tv_sec) { @@ -2207,8 +2207,8 @@ #undef Sleep long -rb_w32_select (int nfds, fd_set *rd, fd_set *wr, fd_set *ex, - struct timeval *timeout) +rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex, + struct timeval *timeout) { long r; fd_set pipe_rd; @@ -2216,11 +2216,29 @@ fd_set else_rd; fd_set else_wr; int nonsock = 0; + struct timeval limit; if (nfds < 0 || (timeout && (timeout->tv_sec < 0 || timeout->tv_usec < 0))) { errno = EINVAL; return -1; } + + if (timeout) { + if (timeout->tv_sec < 0 || + timeout->tv_usec < 0 || + timeout->tv_usec >= 1000000) { + errno = EINVAL; + return -1; + } + gettimeofday(&limit, NULL); + limit.tv_sec += timeout->tv_sec; + limit.tv_usec += timeout->tv_usec; + if (limit.tv_usec >= 1000000) { + limit.tv_usec -= 1000000; + limit.tv_sec++; + } + } + if (!NtSocketsInitialized) { StartSockets(); } @@ -2253,10 +2271,9 @@ struct timeval rest; struct timeval wait; struct timeval zero; - if (timeout) rest = *timeout; wait.tv_sec = 0; wait.tv_usec = 10 * 1000; // 10ms zero.tv_sec = 0; zero.tv_usec = 0; // 0ms - do { + for (;;) { if (nonsock) { // modifying {else,pipe,cons}_rd is safe because // if they are modified, function returns immediately. @@ -2272,8 +2289,7 @@ break; } else { - struct timeval *dowait = - compare(&rest, &wait) < 0 ? &rest : &wait; + struct timeval *dowait = &wait; fd_set orig_rd; fd_set orig_wr; @@ -2287,10 +2303,16 @@ if (wr) *wr = orig_wr; if (ex) *ex = orig_ex; - // XXX: should check the time select spent + if (timeout) { + struct timeval now; + gettimeofday(&now, NULL); + rest = limit; + if (!subtract(&rest, &now)) break; + if (compare(&rest, &wait) < 0) dowait = &rest; + } Sleep(dowait->tv_sec * 1000 + dowait->tv_usec / 1000); } - } while (!timeout || subst(&rest, &wait)); + } } return r; -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/