Ruby の新しい演算子候補 / 標準添付ライブラリ 'thwait'

*>って Ruby の新しい演算子として使えることない? 右側代入とか。同様に +> とか /> とかも使えそう。
~> とかもいけそうだけれど、-> とまちがえやすそう。

関係ないけれど、早く Guild 使ってみたいな。笹田さん、がんばって下さい。



Thread の話。いくつかの Thread をまとめて待つのには、

threads = []
5.times do
  threads << Thread.new {sleep(rand(0.5..1.0))}
end

threads.each {|t| t.join}

みたいなやり方はうまくない。動かないことはないけれど、これでは待っている Thread は常に 1つしかなくて、すべてを同時に待っているのではない。これは標準添付ライブラリの 'thwait' というのを使うとうまくいく。

require 'thwait'

threads = []
5.times do
  threads << Thread.new {p Thread.current; sleep(rand(0.5..1.0))}
end

ThreadsWait.all_waits(*threads) {|t| p t}

これの結果。

#<Thread:0x00005633007e7b18@a6.rb:5 run>
#<Thread:0x00005633007e78e8@a6.rb:5 run>
#<Thread:0x00005633007e7a00@a6.rb:5 run>
#<Thread:0x00005633007e75f0@a6.rb:5 run>
#<Thread:0x00005633007e74d8@a6.rb:5 run>
#<Thread:0x00005633007e75f0@a6.rb:5 dead>
#<Thread:0x00005633007e7a00@a6.rb:5 dead>
#<Thread:0x00005633007e78e8@a6.rb:5 dead>
#<Thread:0x00005633007e74d8@a6.rb:5 dead>
#<Thread:0x00005633007e7b18@a6.rb:5 dead>

こんな風。これどうやっているのだろうとライブラリのソースを読んでみたら、Thread を待つのにさらに Thread と Thread::Queue を使っていた。なるほどなという感じ。


どうでもいいけれど、ムダに凝ってみた。

require 'thwait'

threads = []
5.times do |i|
  threads << Thread.new(i) {|i| puts "Thread #{i} start."; sleep(rand(0.5..1.0))}
end

h = threads.zip([*0..4]).to_h
ThreadsWait.all_waits(*threads) {|t| puts "Thread #{h[t]} is dead."}

結果。

Thread 1 start.
Thread 0 start.
Thread 3 start.
Thread 4 start.
Thread 2 start.
Thread 4 is dead.
Thread 2 is dead.
Thread 1 is dead.
Thread 3 is dead.
Thread 0 is dead

スレッドの開始って順番が保証されないのだな。

Thread とか Fiber っておもしろそうで使ってみたいけれど、何に使ったらいいだろう。「ブロック崩し」みたいなゲームとか?