[#100689] [Ruby master Feature#17303] Make webrick to bundled gems or remove from stdlib — hsbt@...
Issue #17303 has been reported by hsbt (Hiroshi SHIBATA).
11 messages
2020/11/02
[#100852] [Ruby master Feature#17326] Add Kernel#must! to the standard library — zimmerman.jake@...
SXNzdWUgIzE3MzI2IGhhcyBiZWVuIHJlcG9ydGVkIGJ5IGpleiAoSmFrZSBaaW1tZXJtYW4pLg0K
24 messages
2020/11/14
[#100930] [Ruby master Feature#17333] Enumerable#many? — masafumi.o1988@...
Issue #17333 has been reported by okuramasafumi (Masafumi OKURA).
10 messages
2020/11/18
[#101071] [Ruby master Feature#17342] Hash#fetch_set — hunter_spawn@...
Issue #17342 has been reported by MaxLap (Maxime Lapointe).
26 messages
2020/11/25
[ruby-core:100818] [Ruby master Feature#17323] Ractor::LVar to provide ractor-local storage
From:
marcandre-ruby-core@...
Date:
2020-11-12 18:24:49 UTC
List:
ruby-core #100818
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/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>