From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-3.8 required=3.0 tests=AWL,BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS,UNPARSEABLE_RELAY shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from neon.ruby-lang.org (neon.ruby-lang.org [221.186.184.75]) by dcvr.yhbt.net (Postfix) with ESMTP id BE1451F66F for ; Thu, 29 Oct 2020 19:47:32 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id BEF5E120B91; Fri, 30 Oct 2020 04:46:51 +0900 (JST) Received: from xtrwkhkc.outbound-mail.sendgrid.net (xtrwkhkc.outbound-mail.sendgrid.net [167.89.16.28]) by neon.ruby-lang.org (Postfix) with ESMTPS id 66789120B91 for ; Fri, 30 Oct 2020 04:46:49 +0900 (JST) Received: by filterdrecv-p3mdw1-5b99b59cbc-86wjx with SMTP id filterdrecv-p3mdw1-5b99b59cbc-86wjx-19-5F9B1C4E-6A 2020-10-29 19:47:26.981429289 +0000 UTC m=+241626.061837766 Received: from herokuapp.com (unknown) by ismtpd0141p1mdw1.sendgrid.net (SG) with ESMTP id jzy1XxcQSSGxsm3gNpCmqg for ; Thu, 29 Oct 2020 19:47:26.822 +0000 (UTC) Date: Thu, 29 Oct 2020 19:47:27 +0000 (UTC) From: ko1@atdot.net Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 76529 X-Redmine-Project: ruby-master X-Redmine-Issue-Tracker: Feature X-Redmine-Issue-Id: 17273 X-Redmine-Issue-Author: ko1 X-Redmine-Sender: ko1 X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-SG-EID: =?us-ascii?Q?fVTMYOBjtdvXNcWwrscBhLsHItUXVK5L4mtnq0mdcRf1dcJqwEtrqDHKA0UNfP?= =?us-ascii?Q?nE5kLtLtVptNONRxmYqAi9Gy0wv4jAjn9tPO3cV?= =?us-ascii?Q?5X2UYgYm38jjR2eEJpshD7poXEbYJOGy2zj+UIC?= =?us-ascii?Q?C5bFdSP134Mu1OHzX7POGTtxQo4oICAVbhcti2x?= =?us-ascii?Q?EAmhrFMaGg5GYSIfTlGbzXz78KgOio1mycA=3D=3D?= To: ruby-core@ruby-lang.org X-Entity-ID: b/2+PoftWZ6GuOu3b0IycA== X-ML-Name: ruby-core X-Mail-Count: 100657 Subject: [ruby-core:100657] [Ruby master Feature#17273] shareable_constant_value pragma X-BeenThere: ruby-core@ruby-lang.org X-Mailman-Version: 2.1.15 Precedence: list Reply-To: Ruby developers List-Id: Ruby developers List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ruby-core-bounces@ruby-lang.org Sender: "ruby-core" Issue #17273 has been updated by ko1 (Koichi Sasada). Eregon (Benoit Daloze) wrote in #note-16: > I guess it's relatively rare that a gem would (intentionally) expose a non-frozen constant as part of its API, and that the gem relies on being able to mutate it. To confirm it, we will introduce experimental radical API. Other verification methods are welcome. ---------------------------------------- Feature #17273: shareable_constant_value pragma https://bugs.ruby-lang.org/issues/17273#change-88297 * 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 # (Ractor::Error) ``` ## Implementation https://github.com/ruby/ruby/pull/3681/files -- https://bugs.ruby-lang.org/