* thread.c (thread_join): remove the current thread from the join list
of the target thread. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16135 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
62aa7aae51
commit
9c77076296
@ -1,3 +1,8 @@
|
|||||||
|
Tue Apr 22 13:12:58 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* 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@ruby-lang.org>
|
Tue Apr 22 12:03:50 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
* vm_insnhelper.c (vm_get_ev_const): search from the base klass if it
|
* vm_insnhelper.c (vm_get_ev_const): search from the base klass if it
|
||||||
|
@ -213,3 +213,19 @@ assert_equal 'true', %{
|
|||||||
true
|
true
|
||||||
end
|
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
|
||||||
|
}
|
||||||
|
66
thread.c
66
thread.c
@ -461,20 +461,42 @@ rb_thread_create(VALUE (*fn)(ANYARGS), void *arg)
|
|||||||
/* +infty, for this purpose */
|
/* +infty, for this purpose */
|
||||||
#define DELAY_INFTY 1E30
|
#define DELAY_INFTY 1E30
|
||||||
|
|
||||||
static VALUE
|
struct join_arg {
|
||||||
thread_join(rb_thread_t *target_th, double delay)
|
rb_thread_t *target, *waiting;
|
||||||
{
|
double limit;
|
||||||
rb_thread_t *th = GET_THREAD();
|
int forever;
|
||||||
double now, limit = timeofday() + delay;
|
};
|
||||||
|
|
||||||
thread_debug("thread_join (thid: %p)\n", (void *)target_th->thread_id);
|
static VALUE
|
||||||
|
remove_from_join_list(VALUE arg)
|
||||||
|
{
|
||||||
|
struct join_arg *p = (struct join_arg *)arg;
|
||||||
|
rb_thread_t *target_th = p->target, *th = p->waiting;
|
||||||
|
|
||||||
if (target_th->status != THREAD_KILLED) {
|
if (target_th->status != THREAD_KILLED) {
|
||||||
th->join_list_next = target_th->join_list_head;
|
rb_thread_t **pth = &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) {
|
while (target_th->status != THREAD_KILLED) {
|
||||||
if (delay == DELAY_INFTY) {
|
if (p->forever) {
|
||||||
sleep_forever(th);
|
sleep_forever(th);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -482,13 +504,37 @@ thread_join(rb_thread_t *target_th, double delay)
|
|||||||
if (now > limit) {
|
if (now > limit) {
|
||||||
thread_debug("thread_join: timeout (thid: %p)\n",
|
thread_debug("thread_join: timeout (thid: %p)\n",
|
||||||
(void *)target_th->thread_id);
|
(void *)target_th->thread_id);
|
||||||
return Qnil;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
sleep_wait_for_interrupt(th, limit - now);
|
sleep_wait_for_interrupt(th, limit - now);
|
||||||
}
|
}
|
||||||
thread_debug("thread_join: interrupted (thid: %p)\n",
|
thread_debug("thread_join: interrupted (thid: %p)\n",
|
||||||
(void *)target_th->thread_id);
|
(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",
|
thread_debug("thread_join: success (thid: %p)\n",
|
||||||
(void *)target_th->thread_id);
|
(void *)target_th->thread_id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user