@ledsun blog

無味の味は佳境に入らざればすなわち知れず

Ractor.recvの代わりにRactor.selectする

RactorはsendされたメッセージをRactor.recvで受け取ります。 Ractor.selectでも受け取れます。 例えば、次の例です。

r = Ractor.new do
  # message = Ractor.recv と同じ
  _, message = Ractor.select self
  p "Hello #{message}!"
end

r.send 'World'
r.take

実行するとsendされた'World'を結合して、Hello World!を出力します。

Ractor.selectでsendされるメッセージを待てると何がうれしいのでしょうか?

別のRactorをtakeしているときに、自身にsendされるメッセージと別のRactorからのtakeを同時に待てます。 例えば、次の例です。

r1 = Ractor.new do
  Ractor.yield 'r1がyieldしたメッセージ'
  'r1がreturnしたメッセージ'
end

r2 = Ractor.new(r1) do |r1|
  loop do
    # takeとrecvを同時に待つ
    _, message = Ractor.select self, r1
    p message
  end
end

r2.send 'r2にsendしたメッセージ1'
r2.send 'r2にsendしたメッセージ2'

r2.take

実行すると次のように表示されます。

~ ruby select_take_and_recv.rb
"r2にsendしたメッセージ1"
"r2にsendしたメッセージ2"
"r1がyieldしたメッセージ"
"r1がreturnしたメッセージ"