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

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/

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