Skip to content

Preview Ruby 4.1 is a preview. It can change before the final release. Switch to Ruby 4.0 →

class method

Ractor.select

(?) -> ::Array[untyped]
Ractor.select(*ractors_or_ports, timeout: nil) → [ractor or port, obj] or nil

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. With timeout (in seconds) it returns nil instead once the timeout passes. 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.

Example
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

Closing one of the given ports raises Ractor::ClosedError, whether it was closed before the call or while it waits.

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.

Example
values = []
until ractors.empty?
  r, val = Ractor.select(*ractors)
  ractors.delete(r)
  values << val
end

Ruby version changes

  1. 4.0
    • Ractor.select now only accepts Ractors and Ports. If Ractors are given, it returns when a Ractor terminates.

See also .recv .shareable? .receive .shareable_lambda also in 4.0 · 3.4 · 3.3 · 3.2 · 3.1 · 3.0