@ledsun blog

Hのキーがhellで、Sのキーがslaveだ、と彼は思った。そしてYのキーがyouだ。

一度moveしたオブジェクトは移動先のRactorが死んでも帰ってこない

moveしたオブジェクトを参照するとRactor::MovedError

次のRubyスクリプトがあります。

dead = Ractor.new {}
dead.send STDIN, move: true
STDIN.gets

RactorにSTDINをmoveしてから、STDINを使います。 するとRactor::MovedErrorが起きます。

~ ruby dead_and_move.rb
Traceback (most recent call last):
        1: from dead_and_move.rb:5:in `<main>'
dead_and_move.rb:5:in `method_missing': can not send any methods to a moved object (Ractor::MovedError)

move先Ractorが死んでもRactor::MovedError

次のようにmove先のRactorが終了するのを待ちます。

dead = Ractor.new {}
dead.send STDIN, move: true
dead.take # Ractorの終了を待つ
STDIN.gets

結果は変わらず、Ractor::MovedErrorです。

~ ruby dead_and_move.rb
Traceback (most recent call last):
        1: from dead_and_move.rb:4:in `<main>'
dead_and_move.rb:4:in `method_missing': can not send any methods to a moved object (Ractor::MovedError)

moveしたオブジェクトを再び使うには再びmoveする

次のように、Ractorで受け取ったオブジェクトを再度moveすると、メインスレッドで使えます。

dead = Ractor.new do
  Ractor.yield Ractor.recv, move: true # 受け取ったオブジェクトを送り返す
end

dead.send STDIN, move: true
dead.take.gets

一度moveしたオブジェクトは自動的には帰ってきません。 再び使いたければ、明示的に戻します。