From: marcandre-ruby-core@...
Date: 2020-12-10T12:20:37+00:00
Subject: [ruby-core:101388] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
Issue #17323 has been updated by marcandre (Marc-Andre Lafortune).
Eregon (Benoit Daloze) wrote in #note-11:
> For a library, the `Ractor.current[key]` form seems inconvenient as it would need to generate some key, instead of referencing an Ractor::LVar.new object.
I agree using a key does not sound that convenient, but it is a well known API. It's also not too hard to find a key. Instead of storing a `LVar` in `MyGem::Something::REGISTRY`, one can use `:'MyGem::Something::REGISTRY'` as key, there's not much of a difference except it needs to be fully scoped. I don't see other uses than globals for ractor-local storage, right?
The thread-safefy is imo a bigger issue: if there's an easy way (here use `||=` and ignore thread safety) that is almsot safe, and a really hard way that is safe, I fear that the easy way will be taken most of the time.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89147
* 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/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>