[#101179] Spectre Mitigations — Amel <amel.smajic@...>
Hi there!
5 messages
2020/12/01
[#101694] Ruby 3.0.0 Released — "NARUSE, Yui" <naruse@...>
V2UgYXJlIHBsZWFzZWQgdG8gYW5ub3VuY2UgdGhlIHJlbGVhc2Ugb2YgUnVieSAzLjAuMC4gRnJv
4 messages
2020/12/25
[ruby-core:101516] [Ruby master Feature#17378] Ractor#receive with filtering like other actor langauge
From:
ko1@...
Date:
2020-12-18 19:48:18 UTC
List:
ruby-core #101516
Issue #17378 has been updated by ko1 (Koichi Sasada).
I have several concern about `Ractor#receive` proposed at #note-6.
* `NoMatchingPatternError` can be raised in tasks unexpectedly (maybe by bug) and it can cause something strange behavior (like falsy on `receive_if`).
* 2nd parameter `req` is not clear and I believe people forget to call it correctly.
* Not sure how to re-insert (`req.reject`), for example when other threads consumes the incoming queue.
There is no time to discuss enough for ruby 3.0.
Maybe we need a way to write the following code:
```ruby
Ractor.receive do |msg|
case msg
when pat1
[Ractor.receive_commit]
task1(msg)
when pat2
[Ractor.receive_commit]
task2(msg)
when
end
```
`[Ractor.receive_commit]` is a pseudo operation that remove the message from incoming queue.
The above code means "if matched to the pattern, remove the msg from the incoming queue and do the corresponding task, otherwise the msg should be remained in the incoming queue and try to check next message".
To make it with `Ractor.receive_if`, the following code is maybe similar:
```ruby
Ractor.receive_if do
case msg
when pat1
break -> { task1(msg) }
when pat2
break -> { task2(msg) }
end
end.call
```
But nobody want to write such code.
I hope macro will translate something to it.
----
#note-6's approach with similar notation is:
```ruby
Ractor.receive do |msg|
[Ractor.receive_commit]
case msg
in pat1
task1(msg)
in pat2
task2(msg)
else
[Ractor.receive_reject] # or call `req.reject` explicitly
end
end
```
`[Ractor.receive_reject]` is re-insert the message to the incoming queue.
----------------------------------------
Feature #17378: Ractor#receive with filtering like other actor langauge
https://bugs.ruby-lang.org/issues/17378#change-89300
* Author: ko1 (Koichi Sasada)
* Status: Closed
* Priority: Normal
----------------------------------------
With discussion with @marcandre, we found good extension for `Ractor.receive` with block.
```ruby
Ractor.receive do |msg|
if msg is match to condition?
true
else
false
end
end
```
This block iterates incoming queue's values and the value is passed in `msg`.
If the passed value is matched you want to process, the block should return true and the value will be removed from the queue.
Otherwise (returning falsy value), the value remains in the queue, and other `Ractor.receive` accesses it again.
If there is not more values in queue, the interpreter sleeps until new values are received.
```ruby
r = Ractor.new do |;r|
loop do
r, msg = Ractor.receive
r << msg
r << 1
r << 2
r << 3
end
end
r.send([Ractor.current, :ping])
# incoming queue: [:ping, 1, 2, 3] (3 is at the last)
Ractor.receive #=> :ping # without a block
# incoming queue: [1, 2, 3]
p Ractor.receive{|msg| msg == 2}
#=> 2
# incoming queue: [1, 3]
begin
# exception in the block doesn't touch the queue
p Ractor.receive{|msg| raise "err"}
rescue => e
p e.message #=> "err"
end
# incoming queue: [1, 3]
p Ractor.receive #=> 1
# incoming queue: [3]
p Ractor.receive #=> 3
```
With multiple server, we can make it:
```ruby
morning_server = Ractor.new do
loop do
task = Proc.new{|obj| "Good morning #{obj}"}
r, req = Ractor.receive
res = task.(req)
r.send([Ractor.current, res])
end
end
evening_server = Ractor.new do
loop do
task = Proc.new{|obj| "Good evening #{obj}"}
r, req = Ractor.receive
res = task.(req)
r.send([Ractor.current, res])
end
end
morning_server << [Ractor.current, 'ko1']
morning_server << [Ractor.current, 'ko2']
morning_server << [Ractor.current, 'ko3']
evening_server << [Ractor.current, 'ko1']
evening_server << [Ractor.current, 'ko2']
evening_server << [Ractor.current, 'ko3']
def receive r
Ractor.receive{|(from, msg)|
r == from
}[1]
end
p receive(morning_server) #=> "Good morning ko1"
p receive(evening_server) #=> "Good evening ko1"
p receive(morning_server) #=> "Good morning ko2"
p receive(evening_server) #=> "Good evening ko2"
p receive(morning_server) #=> "Good morning ko3"
p receive(evening_server) #=> "Good evening ko3"
```
--
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>