Project

General

Profile

Feature #5788 » patch3.diff

Glass_saga (Masaki Matsushita), 02/01/2012 10:58 PM

View differences:

thread.c
native_thread_init_stack(th);
}
static void thread_run_at_exit(rb_thread_t *th);
static int
thread_start_func_2(rb_thread_t *th, VALUE *stack_start, VALUE *register_stack_start)
{
......
th->value = Qnil;
}
thread_run_at_exit(th);
th->status = THREAD_KILLED;
thread_debug("thread end: %p\n", (void *)th);
......
return str;
}
static void
thread_run_at_exit(rb_thread_t *th)
{
int i;
VALUE args, at_exit;
if(th->at_exit){
at_exit = th->at_exit;
args = rb_ary_new3(1, GET_THREAD()->self);
for (i=RARRAY_LEN(at_exit)-1; i>=0; i--) {
rb_proc_call(RARRAY_PTR(at_exit)[i], args);
}
}
return;
}
void
rb_call_at_exit_proc(VALUE data)
{
VALUE args;
args = rb_ary_new3(1, GET_THREAD()->self);
rb_proc_call(data, args);
}
struct thread_define_at_exit_arg {
rb_thread_t *th;
VALUE proc;
};
static VALUE
thread_define_at_exit(VALUE arg)
{
rb_thread_t *th = ((struct thread_define_at_exit_arg *)arg)->th;
VALUE proc = ((struct thread_define_at_exit_arg *)arg)->proc;
if (th == th->vm->main_thread) {
rb_set_end_proc(rb_call_at_exit_proc, proc);
} else {
if (th->at_exit) {
rb_ary_push(th->at_exit, proc);
} else {
th->at_exit = rb_ary_new3(1, proc);
}
}
return th->self;
}
VALUE
rb_thread_define_at_exit(VALUE thread)
{
rb_thread_t *th;
struct thread_define_at_exit_arg arg;
if (!rb_block_given_p()) {
rb_raise(rb_eArgError, "called without a block");
}
GetThreadPtr(thread, th);
if (rb_threadptr_dead(th)) {
return Qnil;
}
arg.th = th;
arg.proc = rb_block_proc();
if (!th->at_exit_lock) {
th->at_exit_lock = rb_mutex_new();
}
return rb_mutex_synchronize(th->at_exit_lock, thread_define_at_exit, (VALUE)&arg);
}
VALUE
rb_thread_local_aref(VALUE thread, ID id)
{
......
rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
rb_define_method(rb_cThread, "group", rb_thread_group, 0);
rb_define_method(rb_cThread, "backtrace", rb_thread_backtrace_m, 0);
rb_define_method(rb_cThread, "at_exit", rb_thread_define_at_exit, 0);
rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
vm.c
RUBY_MARK_UNLESS_NULL(th->root_fiber);
RUBY_MARK_UNLESS_NULL(th->stat_insn_usage);
RUBY_MARK_UNLESS_NULL(th->last_status);
RUBY_MARK_UNLESS_NULL(th->at_exit);
RUBY_MARK_UNLESS_NULL(th->at_exit_lock);
RUBY_MARK_UNLESS_NULL(th->locking_mutex);
vm_core.h
/* storage */
st_table *local_storage;
VALUE at_exit;
VALUE at_exit_lock;
struct rb_thread_struct *join_list_next;
struct rb_thread_struct *join_list_head;
(3-3/3)