Ractor.make_shareable(proc_obj) makes inner structure shareable
Proc objects are now traversed like other objects when making them shareable. Fixes [Bug #19372] Fixes [Bug #19374]
This commit is contained in:
parent
2183899fd1
commit
d80f3a287c
Notes:
git
2025-03-26 23:05:18 +00:00
@ -1361,6 +1361,28 @@ assert_equal 'true', %q{
|
||||
Ractor.shareable?(pr)
|
||||
}
|
||||
|
||||
# Ractor.make_shareable(a_proc) makes inner structure shareable and freezes it
|
||||
assert_equal 'true,true,true,true', %q{
|
||||
class Proc
|
||||
attr_reader :obj
|
||||
def initialize
|
||||
@obj = Object.new
|
||||
end
|
||||
end
|
||||
|
||||
pr = Ractor.current.instance_eval do
|
||||
Proc.new {}
|
||||
end
|
||||
|
||||
results = []
|
||||
Ractor.make_shareable(pr)
|
||||
results << Ractor.shareable?(pr)
|
||||
results << pr.frozen?
|
||||
results << Ractor.shareable?(pr.obj)
|
||||
results << pr.obj.frozen?
|
||||
results.map(&:to_s).join(',')
|
||||
}
|
||||
|
||||
# Ractor.shareable?(recursive_objects)
|
||||
assert_equal '[false, false]', %q{
|
||||
y = []
|
||||
@ -1389,6 +1411,21 @@ assert_equal '[C, M]', %q{
|
||||
Ractor.make_shareable(ary = [C, M])
|
||||
}
|
||||
|
||||
# Ractor.make_shareable with curried proc checks isolation of original proc
|
||||
assert_equal 'isolation error', %q{
|
||||
a = Object.new
|
||||
orig = proc { a }
|
||||
curried = orig.curry
|
||||
|
||||
begin
|
||||
Ractor.make_shareable(curried)
|
||||
rescue Ractor::IsolationError
|
||||
'isolation error'
|
||||
else
|
||||
'no error'
|
||||
end
|
||||
}
|
||||
|
||||
# define_method() can invoke different Ractor's proc if the proc is shareable.
|
||||
assert_equal '1', %q{
|
||||
class C
|
||||
|
23
ractor.c
23
ractor.c
@ -3045,7 +3045,7 @@ rb_obj_traverse(VALUE obj,
|
||||
}
|
||||
|
||||
static int
|
||||
frozen_shareable_p(VALUE obj, bool *made_shareable)
|
||||
allow_frozen_shareable_p(VALUE obj)
|
||||
{
|
||||
if (!RB_TYPE_P(obj, T_DATA)) {
|
||||
return true;
|
||||
@ -3055,13 +3055,6 @@ frozen_shareable_p(VALUE obj, bool *made_shareable)
|
||||
if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE) {
|
||||
return true;
|
||||
}
|
||||
else if (made_shareable && rb_obj_is_proc(obj)) {
|
||||
// special path to make shareable Proc.
|
||||
rb_proc_ractor_make_shareable(obj);
|
||||
*made_shareable = true;
|
||||
VM_ASSERT(RB_OBJ_SHAREABLE_P(obj));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -3071,20 +3064,24 @@ static enum obj_traverse_iterator_result
|
||||
make_shareable_check_shareable(VALUE obj)
|
||||
{
|
||||
VM_ASSERT(!SPECIAL_CONST_P(obj));
|
||||
bool made_shareable = false;
|
||||
|
||||
if (rb_ractor_shareable_p(obj)) {
|
||||
return traverse_skip;
|
||||
}
|
||||
if (!frozen_shareable_p(obj, &made_shareable)) {
|
||||
if (made_shareable) {
|
||||
return traverse_skip;
|
||||
else if (!allow_frozen_shareable_p(obj)) {
|
||||
if (rb_obj_is_proc(obj)) {
|
||||
rb_proc_ractor_make_shareable(obj);
|
||||
return traverse_cont;
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eRactorError, "can not make shareable object for %"PRIsVALUE, obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (RB_TYPE_P(obj, T_IMEMO)) {
|
||||
return traverse_skip;
|
||||
}
|
||||
|
||||
if (!RB_OBJ_FROZEN_RAW(obj)) {
|
||||
rb_funcall(obj, idFreeze, 0);
|
||||
|
||||
@ -3156,7 +3153,7 @@ shareable_p_enter(VALUE obj)
|
||||
return traverse_skip;
|
||||
}
|
||||
else if (RB_OBJ_FROZEN_RAW(obj) &&
|
||||
frozen_shareable_p(obj, NULL)) {
|
||||
allow_frozen_shareable_p(obj)) {
|
||||
return traverse_cont;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user