End of Life Ruby 3.1 has reached end of life and gets no more fixes. Switch to Ruby 4.0 →
Ractor#take
# File tmp/rubies/ruby-3.1.3/ractor.rb, line 697
def take
__builtin_cexpr! %q{
ractor_take(ec, RACTOR_PTR(self))
}
end
Take a message from ractor’s outgoing port, which was put there by Ractor.yield or at ractor’s finalization.
r = Ractor.new do Ractor.yield 'explicit yield' 'last value' end puts r.take #=> 'explicit yield' puts r.take #=> 'last value' puts r.take # Ractor::ClosedError (The outgoing-port is already closed)
The fact that the last value is also put to outgoing port means that take can be used as some analog of Thread#join (“just wait till ractor finishes”), but don’t forget it will raise if somebody had already consumed everything ractor have produced.
If the outgoing port was closed with close_outgoing, the method will raise Ractor::ClosedError.
r = Ractor.new do sleep(500) Ractor.yield 'Hello from ractor' end r.close_outgoing r.take # Ractor::ClosedError (The outgoing-port is already closed) # The error would be raised immediately, not when ractor will try to receive
If an uncaught exception is raised in the Ractor, it is propagated on take as a Ractor::RemoteError.
r = Ractor.new {raise "Something weird happened"} begin r.take rescue => e p e # => #<Ractor::RemoteError: thrown by remote Ractor.> p e.ractor == r # => true p e.cause # => #<RuntimeError: Something weird happened> end
Ractor::ClosedError is a descendant of StopIteration, so the closing of the ractor will break the loops without propagating the error:
r = Ractor.new do 3.times {|i| Ractor.yield "message #{i}"} "finishing" end loop {puts "Received: " + r.take} puts "Continue successfully"
This will print:
Received: message 0 Received: message 1 Received: message 2 Received: finishing Continue successfully