* [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
@ 2020-11-12 16:55 ko1
2020-11-12 17:07 ` [ruby-core:100817] " ko1
` (17 more replies)
0 siblings, 18 replies; 19+ messages in thread
From: ko1 @ 2020-11-12 16:55 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been reported by ko1 (Koichi Sasada).
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:100817] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
@ 2020-11-12 17:07 ` ko1
2020-11-12 18:24 ` [ruby-core:100818] " marcandre-ruby-core
` (16 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: ko1 @ 2020-11-12 17:07 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by ko1 (Koichi Sasada).
Another advantages compare with current API is,
* we don't need to care about variable name.
* we can make ractor-local constants and instance variables like that:
```ruby
class Fib
attr_reader :cache
def initialize
@cache = Ractor::LVar.new{ {} }
end
private def _fib n
if n < 2
1
else
fib(n-1) + fib(n-2)
end
end
def fib n
if v = @cache.value[n]
v
else
ans = _fib(n)
@cache.value[n] = ans
end
end
end
fiboner = Fib.new
p fiboner.fib(10) #=> 89
pp fiboner.cache.value
#=> {1=>1, 0=>1, 2=>2, 3=>3, 4=>5, 5=>8, 6=>13, 7=>21, 8=>34, 9=>55, 10=>89}
Ractor.new fiboner do |f2|
p f2.fib(5) #=> 8
p f2.cache.value #=> {1=>1, 0=>1, 2=>2, 3=>3, 4=>5, 5=>8}
end.take
```
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-88457
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:100818] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
2020-11-12 17:07 ` [ruby-core:100817] " ko1
@ 2020-11-12 18:24 ` marcandre-ruby-core
2020-11-12 18:44 ` [ruby-core:100819] " ko1
` (15 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: marcandre-ruby-core @ 2020-11-12 18:24 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by marcandre (Marc-Andre Lafortune).
I'm curious for better use cases.
The above example is not very convincing:
- there's no much use in sending this object to a Ractor to start with
- deep-copying the cache is probably faster than having to recalculate part of it
- more importantly, this would probably be the wrong solution if we had `SharedHash`:
```ruby
class SharedHash
def initialize(initial = {})
@ractor = Ractor.new(initial) do |hash|
loop do
case Ractor.receive
in [:read, key, default] then Ractor.yield(hash.fetch(key, default))
in [:write, key, value] then hash[key] = value
in :inspect |
:to_s |
:to_h => cmd then Ractor.yield(hash.send(cmd))
else raise ArgumentError
end
end
end
end
def [](key)
@ractor << [:read, key, nil]
@ractor.take
end
def []=(key, value)
@ractor << [:write, key, value]
value
end
def inspect
@ractor << :inspect
@ractor.take
end
end
class Fib
attr_reader :cache
def initialize
@cache = SharedHash.new
end
private def _fib n
if n < 2
1
else
fib(n-1) + fib(n-2)
end
end
def fib n
@cache[n] ||= _fib(n)
end
end
fiboner = Fib.new
p fiboner.fib(10) #=> 89
pp fiboner.cache
#=> {1=>1, 0=>1, 2=>2, 3=>3, 4=>5, 5=>8, 6=>13, 7=>21, 8=>34, 9=>55, 10=>89}
Ractor.new fiboner do |f2|
p f2.fib(5) #=> 8 already cached!gi
p f2.cache #=> {1=>1, 0=>1, 2=>2, 3=>3, 4=>5, 5=>8, 6=>13, 7=>21, 8=>34, 9=>55, 10=>89}
end.take
```
If the "start from a clear cache" is actually the right idea, than a solution could look like:
```ruby
class Fib
attr_reader :cache
def initialize
@cache = {}
end
def initialize_copy(_)
@cache = {}
end
private def _fib n
if n < 2
1
else
fib(n-1) + fib(n-2)
end
end
def fib n
@cache[n] ||= _fib(n)
end
end
fiboner = Fib.new
p fiboner.fib(10) #=> 89
pp fiboner.cache
#=> {1=>1, 0=>1, 2=>2, 3=>3, 4=>5, 5=>8, 6=>13, 7=>21, 8=>34, 9=>55, 10=>89}
Ractor.new fiboner.dup, move: true do |f2|
p f2.fib(5) #=> 8
p f2.cache.value #=> {1=>1, 0=>1, 2=>2, 3=>3, 4=>5, 5=>8}
end.take
```
Above does not work yet, depends on #17286...
It seems to me that having a way to define how to deep-copy an object might be important.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-88458
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:100819] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
2020-11-12 17:07 ` [ruby-core:100817] " ko1
2020-11-12 18:24 ` [ruby-core:100818] " marcandre-ruby-core
@ 2020-11-12 18:44 ` ko1
2020-11-13 19:53 ` [ruby-core:100842] " daniel
` (14 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: ko1 @ 2020-11-12 18:44 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by ko1 (Koichi Sasada).
marcandre (Marc-Andre Lafortune) wrote in #note-2:
> - deep-copying the cache is probably faster than having to recalculate part of it
> - more importantly, this would probably be the wrong solution if we had `SharedHash`:
it depends on the problem. per-ractor cache is faster to access because there are no synchronization overhead.
Anyway, cache is not a good example.
I wrote it in GH thread https://github.com/ruby/ruby/pull/3762#issuecomment-726227262
> I'm not sure it is a feasible example, but we can set separate configuration between ractors.
> Another idea is to provide unshareable, but similar to global variables, such as Random::DEFAULT which is discussed on https://bugs.ruby-lang.org/issues/17322.
> We can use LVar to implement Ractor::default.
Maybe we can study with the usage of `Thread#thread_variable_get(sym)`.
but not so many https://gist.github.com/ko1/c00020a2c06dceaf9fd5d930e721651e
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-88459
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:100842] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (2 preceding siblings ...)
2020-11-12 18:44 ` [ruby-core:100819] " ko1
@ 2020-11-13 19:53 ` daniel
2020-11-16 7:59 ` [ruby-core:100868] " ko1
` (13 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: daniel @ 2020-11-13 19:53 UTC (permalink / raw)
To: 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:100868] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (3 preceding siblings ...)
2020-11-13 19:53 ` [ruby-core:100842] " daniel
@ 2020-11-16 7:59 ` ko1
2020-12-06 23:20 ` [ruby-core:101271] " marcandre-ruby-core
` (12 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: ko1 @ 2020-11-16 7:59 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by ko1 (Koichi Sasada).
Dan0042 (Daniel DeLorme) wrote in #note-4:
> 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.
Absolutely. By ractor's design, there is a possibility to provide "fork" model, which dup all constants at ractor creation. But we didn't choose (at least now).
> So what I'm saying is that I'd like _something like_ this, that achieves the same effect.
I understand the motivation. But not sure it is easy to use.
Adding `.value` is, it is clear that it is not access constants.
But not so clear it is ractor-local value.
It is disadvantage compare with traditional `Ractor.current[:sym]` approach.
(and I agree adding `.value` for each access is not easy)
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-88515
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101271] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (4 preceding siblings ...)
2020-11-16 7:59 ` [ruby-core:100868] " ko1
@ 2020-12-06 23:20 ` marcandre-ruby-core
2020-12-07 4:26 ` [ruby-core:101275] " marcandre-ruby-core
` (11 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: marcandre-ruby-core @ 2020-12-06 23:20 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by marcandre (Marc-Andre Lafortune).
I'm having difficulties because we don't have Ractor-local storage...
I'd like to implement a Ractor compatible `SharedQueue`.
I'd like to do it without going through a bridge Ractor, so I'm trying to refine `Ractor` to add `channel`s as in #17365.
To do that, I need a Ractor-local "saved messages queue", but there is currently no API for that.
I guess I'll have to roll my own using `Thread.main.thread_variable_get` and wrap the `set` inside a global Mutex...
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-88951
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101275] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (5 preceding siblings ...)
2020-12-06 23:20 ` [ruby-core:101271] " marcandre-ruby-core
@ 2020-12-07 4:26 ` marcandre-ruby-core
2020-12-10 7:06 ` [ruby-core:101363] " matz
` (10 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: marcandre-ruby-core @ 2020-12-07 4:26 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by marcandre (Marc-Andre Lafortune).
In the meantime, I create the gem `ractor-local_variable`.
Code here: https://github.com/ractor-tools/ractor-local_variable/
Of course, `Mutex` is Ractor local... I used a `Ractor` as a basic mutex, there's no other way, right?
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-88955
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101363] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (6 preceding siblings ...)
2020-12-07 4:26 ` [ruby-core:101275] " marcandre-ruby-core
@ 2020-12-10 7:06 ` matz
2020-12-10 10:50 ` [ruby-core:101379] " marcandre-ruby-core
` (9 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: matz @ 2020-12-10 7:06 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by matz (Yukihiro Matsumoto).
I prefer Thread-like Ractor local storage, e.g. `Ractor.current[key]`.
Matz.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89070
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101379] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (7 preceding siblings ...)
2020-12-10 7:06 ` [ruby-core:101363] " matz
@ 2020-12-10 10:50 ` marcandre-ruby-core
2020-12-10 11:43 ` [ruby-core:101382] " eregontp
` (8 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: marcandre-ruby-core @ 2020-12-10 10:50 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by marcandre (Marc-Andre Lafortune).
Will there be a thread-safe way to initialize this storage (other then from the Ractor block)?
Because we can't use a `Mutex` to synchronize as there is no way to initialize the `Mutex` safely either...
Example: A gem needs Ractor-local storage to function. How can they initialize it in a thread-safe manner (other than by asking users of the gem to call `MyLib.initialize_ractor` from the ractor creation block)?
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89138
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101382] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (8 preceding siblings ...)
2020-12-10 10:50 ` [ruby-core:101379] " marcandre-ruby-core
@ 2020-12-10 11:43 ` eregontp
2020-12-10 12:20 ` [ruby-core:101388] " marcandre-ruby-core
` (7 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: eregontp @ 2020-12-10 11:43 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by Eregon (Benoit Daloze).
marcandre (Marc-Andre Lafortune) wrote in #note-10:
> Will there be a thread-safe way to initialize this storage (other then from the Ractor block)?
One possibility, when using `Ractor::LVar.new` would be:
```ruby
LV1 = Ractor::LVar.new do
initial value
end
```
(not unlike Java's `ThreadLocal.withInitial(() -> { ... })`)
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.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89140
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101388] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (9 preceding siblings ...)
2020-12-10 11:43 ` [ruby-core:101382] " eregontp
@ 2020-12-10 12:20 ` marcandre-ruby-core
2020-12-21 20:58 ` [ruby-core:101607] " ko1
` (6 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: marcandre-ruby-core @ 2020-12-10 12:20 UTC (permalink / raw)
To: ruby-core
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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101607] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (10 preceding siblings ...)
2020-12-10 12:20 ` [ruby-core:101388] " marcandre-ruby-core
@ 2020-12-21 20:58 ` ko1
2021-01-06 15:09 ` [ruby-core:101959] " dsisnero
` (5 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: ko1 @ 2020-12-21 20:58 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by ko1 (Koichi Sasada).
Status changed from Open to Closed
Traditional style `Ractor#[]/#[]=` are introduced.
35471a948739ca13b85fe900871e081d553f68e6
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89395
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101959] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (11 preceding siblings ...)
2020-12-21 20:58 ` [ruby-core:101607] " ko1
@ 2021-01-06 15:09 ` dsisnero
2021-01-06 15:11 ` [ruby-core:101960] " chris
` (4 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: dsisnero @ 2021-01-06 15:09 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by dsisnero (Dominic Sisneros).
I don't like the name because it shadows - implies MVAR, TVAR which are known in the functional programming world.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89812
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101960] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (12 preceding siblings ...)
2021-01-06 15:09 ` [ruby-core:101959] " dsisnero
@ 2021-01-06 15:11 ` chris
2021-01-06 16:22 ` [ruby-core:101964] " dsisnero
` (3 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: chris @ 2021-01-06 15:11 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by chrisseaton (Chris Seaton).
> it shadows - implies MVAR, TVAR
I think that's the point isn't it? We have TVar (transactional), MVar (mutable), LVar (local), and matches ivar (instance.)
LVar is a bit overloaded that's true - left-value in terms of assignment - but most short names are.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89813
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101964] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (13 preceding siblings ...)
2021-01-06 15:11 ` [ruby-core:101960] " chris
@ 2021-01-06 16:22 ` dsisnero
2021-01-06 16:25 ` [ruby-core:101965] " chris
` (2 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: dsisnero @ 2021-01-06 16:22 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by dsisnero (Dominic Sisneros).
LVAR is not used much but it is used. http://lambda-the-ultimate.org/node/4823, http://composition.al/blog/2013/09/22/some-example-mvar-ivar-and-lvar-programs-in-haskell/ and it is not
local variable it is a lattice based monotomic container
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89817
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101965] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (14 preceding siblings ...)
2021-01-06 16:22 ` [ruby-core:101964] " dsisnero
@ 2021-01-06 16:25 ` chris
2021-01-07 6:33 ` [ruby-core:101970] " ko1
2021-01-07 13:11 ` [ruby-core:101971] " eregontp
17 siblings, 0 replies; 19+ messages in thread
From: chris @ 2021-01-06 16:25 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by chrisseaton (Chris Seaton).
I don't think there's a massive overlap there, and there's no many letters we could use.
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89818
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101970] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (15 preceding siblings ...)
2021-01-06 16:25 ` [ruby-core:101965] " chris
@ 2021-01-07 6:33 ` ko1
2021-01-07 13:11 ` [ruby-core:101971] " eregontp
17 siblings, 0 replies; 19+ messages in thread
From: ko1 @ 2021-01-07 6:33 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by ko1 (Koichi Sasada).
`Ractor::LocalVariable` ?
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89822
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
* [ruby-core:101971] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
` (16 preceding siblings ...)
2021-01-07 6:33 ` [ruby-core:101970] " ko1
@ 2021-01-07 13:11 ` eregontp
17 siblings, 0 replies; 19+ messages in thread
From: eregontp @ 2021-01-07 13:11 UTC (permalink / raw)
To: ruby-core
Issue #17323 has been updated by Eregon (Benoit Daloze).
I was thinking `Ractor::Local.new` would be fine too, (e.g., Java has `new ThreadLocal()`).
----------------------------------------
Feature #17323: Ractor::LVar to provide ractor-local storage
https://bugs.ruby-lang.org/issues/17323#change-89823
* Author: ko1 (Koichi Sasada)
* Status: Closed
* 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/
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2021-01-07 13:11 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-12 16:55 [ruby-core:100816] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage ko1
2020-11-12 17:07 ` [ruby-core:100817] " ko1
2020-11-12 18:24 ` [ruby-core:100818] " marcandre-ruby-core
2020-11-12 18:44 ` [ruby-core:100819] " ko1
2020-11-13 19:53 ` [ruby-core:100842] " daniel
2020-11-16 7:59 ` [ruby-core:100868] " ko1
2020-12-06 23:20 ` [ruby-core:101271] " marcandre-ruby-core
2020-12-07 4:26 ` [ruby-core:101275] " marcandre-ruby-core
2020-12-10 7:06 ` [ruby-core:101363] " matz
2020-12-10 10:50 ` [ruby-core:101379] " marcandre-ruby-core
2020-12-10 11:43 ` [ruby-core:101382] " eregontp
2020-12-10 12:20 ` [ruby-core:101388] " marcandre-ruby-core
2020-12-21 20:58 ` [ruby-core:101607] " ko1
2021-01-06 15:09 ` [ruby-core:101959] " dsisnero
2021-01-06 15:11 ` [ruby-core:101960] " chris
2021-01-06 16:22 ` [ruby-core:101964] " dsisnero
2021-01-06 16:25 ` [ruby-core:101965] " chris
2021-01-07 6:33 ` [ruby-core:101970] " ko1
2021-01-07 13:11 ` [ruby-core:101971] " eregontp
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).