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; | ||
| }; | ||
| - | ||