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 D9E431FF9C for ; Mon, 26 Oct 2020 16:29:42 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id C6DE812092B; Tue, 27 Oct 2020 01:28:59 +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 1E8C412090B for ; Tue, 27 Oct 2020 01:28:56 +0900 (JST) Received: by filterdrecv-p3las1-bf7bc68d5-8sxdd with SMTP id filterdrecv-p3las1-bf7bc68d5-8sxdd-20-5F96F968-40 2020-10-26 16:29:28.885164878 +0000 UTC m=+426621.196138748 Received: from herokuapp.com (unknown) by geopod-ismtpd-3-4 (SG) with ESMTP id tH1mjth3SGuLUKg_M3Kxkg for ; Mon, 26 Oct 2020 16:29:28.720 +0000 (UTC) Date: Mon, 26 Oct 2020 16:29:28 +0000 (UTC) From: ko1@atdot.net Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 76453 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?fVTMYOBjtdvXNcWwrscBhLsHItUXVK5L4mtnq0mdcRePe5hRlnYFlW=2F+OW5Xfg?= =?us-ascii?Q?AJmMwYbIeUKVLGnMcSYUJtiDBg0L4D0mF3GW9Jr?= =?us-ascii?Q?pYNwFMSSGexmy0mjNof+wGgFxefD1S3JaOLzcmb?= =?us-ascii?Q?3fXjcgb8dc1=2FX9w5KjYCg6bjKnzFCpc+fCikqhU?= =?us-ascii?Q?Xj3JNbTHMHoSZ7FiIOGeCK841D86Or4ICVA=3D=3D?= To: ruby-core@ruby-lang.org X-Entity-ID: b/2+PoftWZ6GuOu3b0IycA== X-ML-Name: ruby-core X-Mail-Count: 100581 Subject: [ruby-core:100581] [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). Today's (yesterday's) dev-meeting: * It is possible to break other library easily: ```ruby require 'other-lib' # sharable_constants: true A = OtherLib::MutableArray # freeze OtherLib::MutableArray accidentally ``` In this case, bug report will be sent to the other-lib's maintainer. It is hard to recognize where the frozen attribute are attached. `Ractor.make_sharable` has same problem, but this pragma can introduce this issue easily (if some guide tell to newbe that "put `shareable_constants: true` at the beginning of file...") We have no conclusion about this issue. ---------------------------------------- Feature #17273: shareable_constant_value pragma https://bugs.ruby-lang.org/issues/17273#change-88213 * 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/