Add a new_thread flag to rb_interrupt_exec
Previously rb_ractor_interrupt_exec would use an intermediate function to create a new thread with the actual target function, replacing the data being passed in with a piece of malloc memory holding the "next" function and the original data. Because of this, passing rb_interrupt_exec_flag_value_data to rb_ractor_interrupt_exec didn't have the intended effect of allowing data to be passed in and marked. This commit adds a rb_interrupt_exec_flag_new_thread flag, which both simplifies the implementation and allows the original data to be marked.
This commit is contained in:
parent
97994c77fb
commit
a34fcf401b
Notes:
git
2025-06-12 20:14:09 +00:00
@ -90,6 +90,7 @@ typedef VALUE (rb_interrupt_exec_func_t)(void *data);
|
||||
enum rb_interrupt_exec_flag {
|
||||
rb_interrupt_exec_flag_none = 0x00,
|
||||
rb_interrupt_exec_flag_value_data = 0x01,
|
||||
rb_interrupt_exec_flag_new_thread = 0x02,
|
||||
};
|
||||
|
||||
// interrupt the target_th and run func.
|
||||
|
36
thread.c
36
thread.c
@ -6206,7 +6206,11 @@ threadptr_interrupt_exec_exec(rb_thread_t *th)
|
||||
RUBY_DEBUG_LOG("task:%p", task);
|
||||
|
||||
if (task) {
|
||||
(*task->func)(task->data);
|
||||
if (task->flags & rb_interrupt_exec_flag_new_thread) {
|
||||
rb_thread_create(task->func, task->data);
|
||||
} else {
|
||||
(*task->func)(task->data);
|
||||
}
|
||||
ruby_xfree(task);
|
||||
}
|
||||
else {
|
||||
@ -6229,43 +6233,15 @@ threadptr_interrupt_exec_cleanup(rb_thread_t *th)
|
||||
rb_native_mutex_unlock(&th->interrupt_lock);
|
||||
}
|
||||
|
||||
struct interrupt_ractor_new_thread_data {
|
||||
rb_interrupt_exec_func_t *func;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static VALUE
|
||||
interrupt_ractor_new_thread_func(void *data)
|
||||
{
|
||||
struct interrupt_ractor_new_thread_data d = *(struct interrupt_ractor_new_thread_data *)data;
|
||||
ruby_xfree(data);
|
||||
|
||||
d.func(d.data);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
interrupt_ractor_func(void *data)
|
||||
{
|
||||
rb_thread_create(interrupt_ractor_new_thread_func, data);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
// native thread safe
|
||||
// func/data should be native thread safe
|
||||
void
|
||||
rb_ractor_interrupt_exec(struct rb_ractor_struct *target_r,
|
||||
rb_interrupt_exec_func_t *func, void *data, enum rb_interrupt_exec_flag flags)
|
||||
{
|
||||
struct interrupt_ractor_new_thread_data *d = ALLOC(struct interrupt_ractor_new_thread_data);
|
||||
|
||||
RUBY_DEBUG_LOG("flags:%d", (int)flags);
|
||||
|
||||
d->func = func;
|
||||
d->data = data;
|
||||
rb_thread_t *main_th = target_r->threads.main;
|
||||
rb_threadptr_interrupt_exec(main_th, interrupt_ractor_func, d, flags);
|
||||
|
||||
// TODO MEMO: we can create a new thread in a ractor, but not sure how to do that now.
|
||||
rb_threadptr_interrupt_exec(main_th, func, data, flags | rb_interrupt_exec_flag_new_thread);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user