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/