Project

General

Profile

Actions

Feature #17273

closed

shareable_constant_value pragma

Added by ko1 (Koichi Sasada) about 1 year ago. Updated 12 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:100466]

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)

Implementation

https://github.com/ruby/ruby/pull/3681/files


Related issues

Related to Ruby master - Feature #17274: Ractor.make_shareable(obj)ClosedActions
Related to Ruby master - Feature #17145: Ractor-aware `Object#deep_freeze`RejectedActions
Related to Ruby master - Feature #17278: On-demand sharing of constants for RactorFeedbackActions
Related to Ruby master - Feature #17397: `shareable_constant_value: literal` should check at runtime, not at parse timeClosedko1 (Koichi Sasada)Actions
Actions

Also available in: Atom PDF