Feature #10187 » inline_storage-16.patch
insns.def | ||
---|---|---|
{
|
||
union iseq_inline_storage_entry *is = (union iseq_inline_storage_entry *)ic;
|
||
#define RUNNING_THREAD_ONCE_DONE ((rb_thread_t *)(0x1))
|
||
retry:
|
||
if (is->once.done == Qfalse) {
|
||
if (is->once.running_thread == NULL) {
|
||
is->once.running_thread = th;
|
||
val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is);
|
||
/* is->once.running_thread is cleared by vm_once_clear() */
|
||
is->once.done = Qtrue;
|
||
rb_iseq_add_mark_object(GET_ISEQ(), val);
|
||
}
|
||
else if (is->once.running_thread == th) {
|
||
/* recursive once */
|
||
val = vm_once_exec((VALUE)iseq);
|
||
}
|
||
else {
|
||
/* waiting for finish */
|
||
RUBY_VM_CHECK_INTS(th);
|
||
rb_thread_schedule();
|
||
goto retry;
|
||
}
|
||
if (is->once.running_thread == RUNNING_THREAD_ONCE_DONE) {
|
||
val = is->once.value;
|
||
}
|
||
else if (is->once.running_thread == NULL) {
|
||
is->once.running_thread = th;
|
||
val = is->once.value = rb_ensure(vm_once_exec, (VALUE)iseq, vm_once_clear, (VALUE)is);
|
||
/* is->once.running_thread is cleared by vm_once_clear() */
|
||
is->once.running_thread = RUNNING_THREAD_ONCE_DONE; /* success */
|
||
rb_iseq_add_mark_object(GET_ISEQ(), val);
|
||
}
|
||
else if (is->once.running_thread == th) {
|
||
/* recursive once */
|
||
val = vm_once_exec((VALUE)iseq);
|
||
}
|
||
else {
|
||
val = is->once.value;
|
||
/* waiting for finish */
|
||
RUBY_VM_CHECK_INTS(th);
|
||
rb_thread_schedule();
|
||
goto retry;
|
||
}
|
||
}
|
||
vm_core.h | ||
---|---|---|
struct {
|
||
struct rb_thread_struct *running_thread;
|
||
VALUE value;
|
||
VALUE done;
|
||
} once;
|
||
struct iseq_inline_cache_entry cache;
|
||
};
|
||
-
|