[#121215] [Ruby master Bug#21166] Fiber Scheduler is unable to be interrupted by `IO#close`. — "ioquatix (Samuel Williams) via ruby-core" <ruby-core@...>

Issue #21166 has been reported by ioquatix (Samuel Williams).

13 messages 2025/03/02

[#121222] [Ruby master Bug#21167] Visual Studio 2022 17.13.x couldn't build ruby.exe — "hsbt (Hiroshi SHIBATA) via ruby-core" <ruby-core@...>

Issue #21167 has been reported by hsbt (Hiroshi SHIBATA).

8 messages 2025/03/03

[#121234] [Ruby master Bug#21168] Prism doesn't require argument parentheses (in some cases) when a block is present but parse.y does — "Earlopain (Earlopain _) via ruby-core" <ruby-core@...>

Issue #21168 has been reported by Earlopain (Earlopain _).

8 messages 2025/03/04

[#121389] [Ruby Bug#21187] Strings concatenated with `\` getting frozen with literal hashes (PRISM only) — LocoDelAssembly via ruby-core <ruby-core@...>

Issue #21187 has been reported by LocoDelAssembly (Hern=E1n Pereira).

12 messages 2025/03/17

[#121413] [Ruby Bug#21193] Inherited callback returns `nil` for `Object.const_source_location` — "eileencodes (Eileen Uchitelle) via ruby-core" <ruby-core@...>

Issue #21193 has been reported by eileencodes (Eileen Uchitelle).

15 messages 2025/03/20

[#121451] [Ruby Bug#21201] Performance regression when defining methods inside `refine` blocks — "alpaca-tc (Hiroyuki Ishii) via ruby-core" <ruby-core@...>

Issue #21201 has been reported by alpaca-tc (Hiroyuki Ishii).

8 messages 2025/03/27

[ruby-core:121303] [Ruby master Feature#21121] Ractor channels

From: "luke-gru (Luke Gruber) via ruby-core" <ruby-core@...>
Date: 2025-03-11 22:42:47 UTC
List: ruby-core #121303
Issue #21121 has been updated by luke-gru (Luke Gruber).


Ruby internals uses this same trick to simplify getting `require` calls to work in non-main ractors. The code is here: https://github.com/ruby/ruby/blob/master/ractor.c#L4009. It simply starts a new thread on the main ractor, calls the require there and then sends a message over that pseudo-channel to inform the calling ractor that it's done. I don't know if that was where you got the idea or great minds just think alike :)

Obviously it's a bit of a hack and is less performant than if there were proper channels in the language, but it gets the job done for now.



----------------------------------------
Feature #21121: Ractor channels
https://bugs.ruby-lang.org/issues/21121#change-112265

* Author: luke-gru (Luke Gruber)
* Status: Open
----------------------------------------
# Motivation:

It would be nice be able to `Ractor.yield` in a non-blocking way. Right now a `Ractor.yield` blocks until another ractor calls `r.take` on the yielding ractor.
This is bad in the following scenario:

```ruby
main = Ractor.current

rs = 10.times.map do
  Ractor.new(main) do |m|
    ret = []
    loop do
      # do a bunch of work that takes a while, then:
      begin
        obj = m.take
      rescue Ractor::ClosedError
      end
      if obj
        ret << obj
      else
        break
      end
    end
    ret
  end
end

50.times do |i|
  Ractor.yield(i) # this will block until some ractor calls take on us, but it could be a while if there is processing before the `take` call.
end
main.close_outgoing

# Ideally, we could do some work in main ractor that takes some time while the other ractors do their processing. But we're blocking right now
# during all the calls to `Ractor.yield`.

# Finally, get the results
while rs.any?
  r, obj = Ractor.select(*rs)
  $stderr.puts "Ractor #{r} got #{obj}"
  rs.delete(r)
end
```

I'd like other ractors to be able to do work in a "fire and forget" kind of way. It isn't possible right now due to the limitations of `Ractor.yield` and `Ractor#take`.
What we need is some kind of `yield` buffer so the yielder doesn't block. I propose that Ractor channels would allow this type of programming to work.

## Example using channels:


```ruby
chan = Ractor::Channel.new # We could specify buffer size like Go or it could be dynamically growable

rs = 10.times.map do
  Ractor.new(chan) do |c|
    ret = []
    loop do
      obj, _closed = c.receive # returns `[nil, true]` if `c` is closed and its buffer is empty. It blocks if the buffer is empty and `c` is not closed.
      if obj
        ret << obj
      else
        break
      end
    end
    ret
  end
end

50.times do |i|
  chan.send(i) # non-blocking, fills a buffer and only wakes a receiver if there is one
end
chan.close

# Do some processing while ractors do their work.

# Then, collect the results
while rs.any?
  r, obj = Ractor.select(*rs)
  puts "Ractor #{r} got #{obj}"
  rs.delete(r)
end
```

With an API similar to this, we could have "fire and forget" processing with ractors.



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/


In This Thread