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 D3EF11F66F for ; Fri, 13 Nov 2020 19:53:50 +0000 (UTC) Received: from neon.ruby-lang.org (localhost [IPv6:::1]) by neon.ruby-lang.org (Postfix) with ESMTP id 098EC120B21; Sat, 14 Nov 2020 04:53:06 +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 70209120B1F for ; Sat, 14 Nov 2020 04:53:04 +0900 (JST) Received: by filterdrecv-p3las1-8659fd955-lcflr with SMTP id filterdrecv-p3las1-8659fd955-lcflr-19-5FAEE445-47 2020-11-13 19:53:41.688080447 +0000 UTC m=+230147.231478528 Received: from herokuapp.com (unknown) by ismtpd0017p1iad2.sendgrid.net (SG) with ESMTP id hz47KPg6QLSEywwIdTz-nw for ; Fri, 13 Nov 2020 19:53:41.520 +0000 (UTC) Date: Fri, 13 Nov 2020 19:53:41 +0000 (UTC) From: daniel@dan42.com Message-ID: References: Mime-Version: 1.0 X-Redmine-MailingListIntegration-Message-Ids: 76716 X-Redmine-Project: ruby-master X-Redmine-Issue-Tracker: Feature X-Redmine-Issue-Id: 17323 X-Redmine-Issue-Author: ko1 X-Redmine-Sender: Dan0042 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?8sy4RigFvRTdBfCVJrT9zb2J88PC92TMQwdNgaWYaq7aMJK=2FiaydDCFNfyy481?= =?us-ascii?Q?W4zMp3n1+6age8aX1E10WjMy8UU7jO7Rjxymy1B?= =?us-ascii?Q?nOelZ2A7ExTkQ8BlCeqFtM0RB+tMipE9czVvmvB?= =?us-ascii?Q?l=2FWM953c7+lbBIgs2W5cPpgYVGI67pp+caRA6uW?= =?us-ascii?Q?Ce4HsSPqUgPrqj+EkD7dudNUOY0QkkROUJyP4Kk?= =?us-ascii?Q?Tl40PhiW6m4kl4sY0=3D?= To: ruby-core@ruby-lang.org X-Entity-ID: b/2+PoftWZ6GuOu3b0IycA== X-ML-Name: ruby-core X-Mail-Count: 100842 Subject: [ruby-core:100842] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage 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 #17323 has been updated by Dan0042 (Daniel DeLorme). Would it be possible to somehow have ractor-local variables that are automatically dereferenced instead of having to append `.value` everywhere? I'm thinking of cases like this where a class-level mutable constant (or classvar) makes it hard to make this code compatible with ractors. ```ruby class X # original, not compatible with Ractor, so how do we fix? CACHE = {} # like this, except now we need to append .value to every CACHE access CACHE = Ractor::LVar.new{ {} } def initialize(value) @value = value end def analyzed # here, lookup of CACHE constant could automatically return the # ractor-local Hash inside the LVar instead of the LVar itself CACHE[@value] ||= analyze(@value) end end ``` The problem with the example above is that it's too magical to have a variable or constant return an object different from what was assigned. So what I'm saying is that I'd like _something like_ this, that achieves the same effect. I have the feeling that a different syntax would be needed, to differentiate it from assignment. Maybe `CONST: expr` could be used to lazily evaluate `expr` once per ractor; then it would make sense for `CONST` to return this value rather than the LVar used behind the scenes. The example above would become `CACHE: {}`. But of course introducing new syntax is not something to be done lightly. ---------------------------------------- Feature #17323: Ractor::LVar to provide ractor-local storage https://bugs.ruby-lang.org/issues/17323#change-88484 * Author: ko1 (Koichi Sasada) * Status: Open * Priority: Normal ---------------------------------------- Ruby supports thread and fiber local storage: * `Thread#[sym]` provides *Fiber* local storage * `Thread#thread_variable_get(sym) These APIs can access other threads/fibers like that: ```ruby th = Thread.new{ Thread.current.thread_variable_set(:a, 10) } th.join # access from main thread to child thread p th.thread_variable_get(:a) ``` To make Ractor local storage, this kind of feature should not be allowed to protect isolation. This ticket propose alternative API `Ractor::LVar` that allows to provide Ractor local variable. ```ruby LV1 = Ractor::LVar.new p LV1.value #=> nil # default value LV1.value = 'hello' # can set unshareable objects because LVar is ractor local. Ractor.new do LV1.value = 'world' # set Ractor local variable end.take p LV1.value #=> 'hello' # Lvar.new can accept default_proc which should be isolated Proc. LV2 = Ractor::LVar.new{ "x" * 4 } p LV2.value #=> "xxxx" LV2.value = 'yyy' Ractor.new do p LV2.value #=> 'xxx' end p LV2.value #=> 'yyy' ``` This API doesn't support accessing from other ractors. `Ractor::LVar` is from `Ractor::TVar`, but I have no strong opinion about it. For example, `Ractor::LocalVariable` is longer and clearer. Implementation: https://github.com/ruby/ruby/pull/3762 -- https://bugs.ruby-lang.org/