やることは前回と同じです。Ractorの構成を組み替えてみました。
Pull型とPush型
Ractorのメッセージ送受信にはPull型とPush型があります。 前回、メインスレッド(?)でRactorインスタンスをselectしてイベントを待ちました。Pull型です。
今回、描画用のRactorインスタンスrendererを用意して、他のRactorインスタンスからイベントをsendします。Push型です。
完成形
require 'io/console' # 結果を描画するRactor。inputとclockの存在を知りません。 renderer = Ractor.new do val = 0 loop do # メッセージを待ちます msg = Ractor.recv # メッセージがユーザー入力だったら値をリセットします。 val = 0 if msg == :reset # カウントアップします。 val += 1 # 行をクリア print "\e[2K" # 行頭へ移動 print "\e[0G" # 出力 print val end end # ユーザー入力を待つRactor。引数でrendererを受け取ります。 input = Ractor.new renderer do |renderer| # moveされたSTDIOを使って文字入力を待つ io = Ractor.recv while "\C-c" != io.getch # メッセージを送ります renderer << :reset end end # クロックイベントを発生するRactor。引数でrendererを受け取ります。 Ractor.new renderer do |renderer| loop do # メッセージを送ります renderer << nil sleep 0.3 end end # 共有不可能オブジェクトSTDINをRactorにmoveする input.send STDIN, move: true # Ractorの終了を待つ? Ractor.recv
はまったところ
Ractor.recv
を書かずに実行したら、何も出力されずにプログラムが終了しました。
Ractorインスタンスが動き出す前に、メインスレッド(?)が終了したようです。
感想
Pull型とPush型では、Ractor間の依存関係が逆転しました。 この規模では、ふーんて感じです。