From: eregontp@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:100654] [Ruby master Feature#17273] shareable_constant_value pragma
Date: Thu, 29 Oct 2020 19:33:43 +0000 (UTC) [thread overview]
Message-ID: <redmine.journal-88294.20201029193342.17@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-17273.20201021055619.17@ruby-lang.org
Issue #17273 has been updated by Eregon (Benoit Daloze).
Eregon (Benoit Daloze) wrote in #note-14:
> Of course, no gems should directly mutate constants of another gem.
I missed that the gem doesn't need to mutate `A` to break `OtherLib`.
I guess it's relatively rare that a gem would expose a non-frozen constant as part of its API, and that the gem relies on being able to mutate it.
----------------------------------------
Feature #17273: shareable_constant_value pragma
https://bugs.ruby-lang.org/issues/17273#change-88294
* Author: ko1 (Koichi Sasada)
* Status: Open
* Priority: Normal
----------------------------------------
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.
```ruby
# 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.
```ruby
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.
```ruby
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.
```ruby
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.
```ruby
# 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.
```ruby
# 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.
```ruby
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.
```ruby
# 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:
```ruby
# 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
--
https://bugs.ruby-lang.org/
next prev parent reply other threads:[~2020-10-29 19:33 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-21 5:56 [ruby-core:100466] [Ruby master Feature#17273] shareable_constant_value pragma ko1
2020-10-21 18:58 ` [ruby-core:100477] " eregontp
2020-10-22 0:46 ` [ruby-core:100484] " ko1
2020-10-22 0:52 ` [ruby-core:100485] " ko1
2020-10-23 21:23 ` [ruby-core:100517] " marcandre-ruby-core
2020-10-25 12:57 ` [ruby-core:100528] " eregontp
2020-10-26 16:29 ` [ruby-core:100581] " ko1
2020-10-29 16:14 ` [ruby-core:100647] " ko1
2020-10-29 19:26 ` [ruby-core:100652] " eregontp
2020-10-29 19:29 ` [ruby-core:100653] " eregontp
2020-10-29 19:33 ` eregontp [this message]
2020-10-29 19:47 ` [ruby-core:100657] " ko1
2020-10-29 19:53 ` [ruby-core:100659] " merch-redmine
2020-12-16 18:36 ` [ruby-core:101473] " marcandre-ruby-core
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.ruby-lang.org/en/community/mailing-lists/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=redmine.journal-88294.20201029193342.17@ruby-lang.org \
--to=ruby-core@ruby-lang.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).