Feature #5958 ยป patch.diff
| test/ruby/test_thread.rb | ||
|---|---|---|
|
end
|
||
|
assert_in_delta(t1 - t0, 1, 1)
|
||
|
end
|
||
|
def test_join
|
||
|
thgrp = ThreadGroup.new
|
||
|
thgrp.add(t = Thread.new{ sleep })
|
||
|
t0 = Time.now.to_f
|
||
|
assert_nil(thgrp.join(1))
|
||
|
t1 = Time.now.to_f
|
||
|
assert_in_delta(t1 - t0, 1, 1)
|
||
|
ensure
|
||
|
t.kill if t
|
||
|
end
|
||
|
end
|
||
| thread.c | ||
|---|---|---|
|
return ary;
|
||
|
}
|
||
|
struct thgroup_join_params {
|
||
|
double limit;
|
||
|
VALUE group;
|
||
|
};
|
||
|
static int
|
||
|
thgroup_join_i(st_data_t key, st_data_t value, st_data_t data)
|
||
|
{
|
||
|
VALUE thread = (VALUE)key;
|
||
|
rb_thread_t *th;
|
||
|
struct thgroup_join_params *args = (struct thgroup_join_params *)data;
|
||
|
double delay = args->limit;
|
||
|
GetThreadPtr(thread, th);
|
||
|
if (th->thgroup == args->group) {
|
||
|
if (delay != DELAY_INFTY) delay -= timeofday();
|
||
|
if (NIL_P(thread_join(th, delay))) {
|
||
|
args->group = Qnil;
|
||
|
return ST_STOP;
|
||
|
}
|
||
|
}
|
||
|
return ST_CONTINUE;
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* thgrp.join -> thgrp
|
||
|
* thgrp.join(limit) -> thgrp or nil
|
||
|
*
|
||
|
* The calling thread will suspend execution until threads in the receiving
|
||
|
* <code>ThreadGroup</code> exit or until <i>limit</i> seconds have passed.
|
||
|
* If the time limit expires, <code>nil</code> will be returned, otherwise
|
||
|
* <i>thgrp</i> is returned.
|
||
|
*
|
||
|
*/
|
||
|
static VALUE
|
||
|
thgroup_join(int argc, VALUE *argv, VALUE self)
|
||
|
{
|
||
|
VALUE limit;
|
||
|
struct thgroup_join_params param;
|
||
|
rb_scan_args(argc, argv, "01", &limit);
|
||
|
if (!NIL_P(limit)) {
|
||
|
param.limit = timeofday() + rb_num2dbl(limit);
|
||
|
} else {
|
||
|
param.limit = DELAY_INFTY;
|
||
|
}
|
||
|
param.group = self;
|
||
|
st_foreach(GET_THREAD()->vm->living_threads, thgroup_join_i, (st_data_t) & param);
|
||
|
return param.group;
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
| ... | ... | |
|
rb_define_method(cThGroup, "enclose", thgroup_enclose, 0);
|
||
|
rb_define_method(cThGroup, "enclosed?", thgroup_enclosed_p, 0);
|
||
|
rb_define_method(cThGroup, "add", thgroup_add, 1);
|
||
|
rb_define_method(cThGroup, "join", thgroup_join, -1);
|
||
|
{
|
||
|
th->thgroup = th->vm->thgroup_default = rb_obj_alloc(cThGroup);
|
||