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

ruby-changes:4641

From: ko1@a...
Date: Tue, 22 Apr 2008 13:13:24 +0900 (JST)
Subject: [ruby-changes:4641] nobu - Ruby:r16135 (trunk): * thread.c (thread_join): remove the current thread from the join list

nobu	2008-04-22 13:13:01 +0900 (Tue, 22 Apr 2008)

  New Revision: 16135

  Modified files:
    trunk/ChangeLog
    trunk/bootstraptest/test_thread.rb
    trunk/thread.c

  Log:
    * thread.c (thread_join): remove the current thread from the join list
      of the target thread.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=16135&r2=16134&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/thread.c?r1=16135&r2=16134&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_thread.rb?r1=16135&r2=16134&diff_format=u

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 16134)
+++ ChangeLog	(revision 16135)
@@ -1,3 +1,8 @@
+Tue Apr 22 13:12:58 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* thread.c (thread_join): remove the current thread from the join list
+	  of the target thread.
+
 Tue Apr 22 12:03:50 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* vm_insnhelper.c (vm_get_ev_const): search from the base klass if it
Index: bootstraptest/test_thread.rb
===================================================================
--- bootstraptest/test_thread.rb	(revision 16134)
+++ bootstraptest/test_thread.rb	(revision 16135)
@@ -213,3 +213,19 @@
     true
   end
 }
+
+assert_finish 3, %{
+  th = Thread.new {sleep 2}
+  th.join(1)
+  th.join
+}
+
+assert_finish 3, %{
+  require 'timeout'
+  th = Thread.new {sleep 2}
+  begin
+    Timeout.timeout(1) {th.join}
+  rescue Timeout::Error
+  end
+  th.join
+}
Index: thread.c
===================================================================
--- thread.c	(revision 16134)
+++ thread.c	(revision 16135)
@@ -461,20 +461,42 @@
 /* +infty, for this purpose */
 #define DELAY_INFTY 1E30
 
+struct join_arg {
+    rb_thread_t *target, *waiting;
+    double limit;
+    int forever;
+};
+
 static VALUE
-thread_join(rb_thread_t *target_th, double delay)
+remove_from_join_list(VALUE arg)
 {
-    rb_thread_t *th = GET_THREAD();
-    double now, limit = timeofday() + delay;
+    struct join_arg *p = (struct join_arg *)arg;
+    rb_thread_t *target_th = p->target, *th = p->waiting;
 
-    thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
+    if (target_th->status != THREAD_KILLED) {
+	rb_thread_t **pth = &target_th->join_list_head;
 
-    if (target_th->status != THREAD_KILLED) {
-	th->join_list_next = target_th->join_list_head;
-	target_th->join_list_head = th;
+	while (*pth) {
+	    if (*pth == th) {
+		*pth = th->join_list_next;
+		break;
+	    }
+	    pth = &(*pth)->join_list_next;
+	}
     }
+
+    return Qnil;
+}
+
+static VALUE
+thread_join_sleep(VALUE arg)
+{
+    struct join_arg *p = (struct join_arg *)arg;
+    rb_thread_t *target_th = p->target, *th = p->waiting;
+    double now, limit = p->limit;
+
     while (target_th->status != THREAD_KILLED) {
-	if (delay == DELAY_INFTY) {
+	if (p->forever) {
 	    sleep_forever(th);
 	}
 	else {
@@ -482,14 +504,38 @@
 	    if (now > limit) {
 		thread_debug("thread_join: timeout (thid: %p)\n",
 			     (void *)target_th->thread_id);
-		return Qnil;
+		return Qfalse;
 	    }
 	    sleep_wait_for_interrupt(th, limit - now);
 	}
 	thread_debug("thread_join: interrupted (thid: %p)\n",
 		     (void *)target_th->thread_id);
     }
+    return Qtrue;
+}
 
+static VALUE
+thread_join(rb_thread_t *target_th, double delay)
+{
+    rb_thread_t *th = GET_THREAD();
+    struct join_arg arg;
+
+    arg.target = target_th;
+    arg.waiting = th;
+    arg.limit = timeofday() + delay;
+    arg.forever = delay == DELAY_INFTY;
+
+    thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
+
+    if (target_th->status != THREAD_KILLED) {
+	th->join_list_next = target_th->join_list_head;
+	target_th->join_list_head = th;
+	if (!rb_ensure(thread_join_sleep, (VALUE)&arg,
+		       remove_from_join_list, (VALUE)&arg)) {
+	    return Qnil;
+	}
+    }
+
     thread_debug("thread_join: success (thid: %p)\n",
 		 (void *)target_th->thread_id);
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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