Select in Ruby
Our example demonstrates how to wait on multiple channel operations using Ruby’s Thread
and Queue
classes. This combination provides a powerful feature for concurrent programming in Ruby.
require 'thread'
def main
# For our example we'll select across two queues.
q1 = Queue.new
q2 = Queue.new
# Each queue will receive a value after some amount
# of time, to simulate e.g. blocking RPC operations
# executing in concurrent threads.
Thread.new do
sleep(1)
q1.push("one")
end
Thread.new do
sleep(2)
q2.push("two")
end
# We'll use a loop to await both of these values
# simultaneously, printing each one as it arrives.
2.times do
Thread.new do
result = Queue.new
Thread.new { result.push([:q1, q1.pop]) }
Thread.new { result.push([:q2, q2.pop]) }
queue, msg = result.pop
puts "received #{msg}"
end.join
end
end
main
We receive the values "one"
and then "two"
as expected.
$ time ruby select.rb
received one
received two
Note that the total execution time is only ~2 seconds since both the 1 and 2 second sleep
operations execute concurrently.
real 0m2.245s
In this Ruby implementation, we use Thread
to create concurrent operations and Queue
to simulate channels. The select
functionality is mimicked by creating separate threads for each queue and using another queue (result
) to collect the first available message. This approach allows us to wait on multiple operations simultaneously, similar to Go’s select
.