Ractor.select
# File tmp/rubies/ruby-4.0.0/ractor.rb, line 308
def self.select(*ports)
raise ArgumentError, 'specify at least one Ractor::Port or Ractor' if ports.empty?
monitors = {} # Ractor::Port => Ractor
ports = ports.map do |arg|
case arg
when Ractor
port = Ractor::Port.new
monitors[port] = arg
arg.monitor port
port
when Ractor::Port
arg
else
raise ArgumentError, "should be Ractor::Port or Ractor"
end
end
begin
result_port, obj = __builtin_ractor_select_internal(ports)
if r = monitors[result_port]
[r, r.value]
else
[result_port, obj]
end
ensure
# close all ports for join
monitors.each do |port, r|
r.unmonitor port
port.close
end
end
end
Blocks the current Thread until one of the given ports has received a message. Returns an array of two elements where the first element is the Port and the second is the received object. This method can also accept Ractor objects themselves, and in that case will wait until one has terminated and return a two-element array where the first element is the ractor and the second is its termination value.
p1, p2 = Ractor::Port.new, Ractor::Port.new ps = [p1, p2] rs = 2.times.map do |i| Ractor.new(ps.shift, i) do |p, i| sleep rand(0.99) p.send("r#{i}") sleep rand(0.99) "r#{i} done" end end waiting_on = [p1, p2, *rs] until waiting_on.empty? received_on, obj = Ractor.select(*waiting_on) waiting_on.delete(received_on) puts obj end # r0 # r1 # r1 done # r0 done
The following example is almost equivalent to ractors.map(&:value) except the thread is unblocked when any of the ractors has terminated as opposed to waiting for their termination in the array element order.
values = [] until ractors.empty? r, val = Ractor.select(*ractors) ractors.delete(r) values << val end
Ruby version changes
-
4.0
-
Ractor.selectnow only accepts Ractors and Ports. If Ractors are given, it returns when aRactorterminates.
-