Feature #17273
closedshareable_constant_value pragma
Description
This proposal is to introduce # shareable_constant_value: true
pragma to make constant values shareable objects.
With this pragma, you don't need to add freeze
to access from non-main ractors.
# shareable_constant_value: true
A = [1, [2, [3, 4]]]
H = {a: "a"}
Ractor.new do
p A
p H
end.take
Background¶
Now, we can not access constants which contains a unshareable object from the non-main Ractor.
A = [1, [2, [3, 4]]]
H = {a: "a"}
Ractor.new do
p A #=> can not access non-sharable objects in constant Object::A by non-main Ractor. (NameError)
p H
end.take
If we know we don't modify A
and H
is frozen object, we can freeze them, and other ractors can access them.
A = [1, [2, [3, 4].freeze].freeze].freeze
H = {a: "a".freeze}.freeze
Ractor.new do
p A #=> [1, [2, [3, 4]]]
p H #=> {:a=>"a"}
end.take
Adding nesting data structure, we need many .freeze
method.
Recently, I added Ractor.make_shareable(obj)
makes obj
shareable with freezing objects deeply (see [Feature #17274]).
We only need to introduce this method for each constant.
A = Ractor.make_shareable( [1, [2, [3, 4]]] )
H = Ractor.make_shareable( {a: "a"} )
Ractor.new do
p A #=> [1, [2, [3, 4]]]
p H #=> {:a=>"a"}
end.take
However, if we have 100 constants, it is troublesome.
Proposal¶
With # shareable_constant_value: true
, you can specify all constants are shareable.
# shareable_constant_value: true
A = [1, [2, [3, 4]]]
# compiled with: A = Ractor.make_shareable( [1, [2, [3, 4]]] )
H = {a: "a"}
# compiled with: H = Ractor.make_shareable( {a: "a"} )
Ractor.new do
p A
p H
end.take
(Strictly speaking, don't call Ractor.make_shareable
, but apply same effect. This means rewriting Ractor.make_shareable
doesn't affect this behavior)
You can specify # shareable_constant_value: false
in the middle of the place.
# shareable_constant_value: true
S1 = 'str' #
p S1.frozen? #=> true
# shareable_constant_value: false
S2 = 'str' #
p S2.frozen? #=> false
The effect of this pragma is closed to the scope.
class C
# shareable_constant_value: true
A = 'str'
p A.frozen? #=> true
1.times do
# shareable_constant_value: false
B = 'str'
p B.frozen? #=> false
end
end
X = 'str'
p X.frozen? #=> false
Ractor.make_shareable(obj)
doesn't affect anything to shareable objects.
# shareable_constant_value: true
class C; end
D = C
p D.frozen? #=> false
Some objects can not become shareable objects, so it raises an exception:
# shareable_constant_value: true
T = Thread.new{}
#=> `make_shareable': can not make shareable object for #<Thread:0x000055952e40ffb0 /home/ko1/ruby/src/trunk/test.rb:3 run> (Ractor::Error)