パーフェクトRubyを読んでいて目に止まったので、Ruby 1.9から導入すあれた軽量スレッドFiberを使ってみよう。
ThreadとFiberの最大の違いは、コンテキストの切り替えをプログラマが明示的に指定することだ。 Fiberを使えば、結果全体を作るのに大きなコストのかかる処理を段階的に実行させて、部分的な結果を随時取り出すような実装が可能になる。
FiberはFiber.newで生成し、ブロックでFiberで実行する処理内容を記述する。Fiberの実行はFiber#resumeの呼び出しで行う。処理はFiber.yieldでいったん停止して、呼び出し元に戻る。停止したFiberの再実行は、同じくFiber#resumeで行う。実行できる処理がなくなった状態でFiber#resumeを呼び出すと、FiberErrorが発生する。
fiber = Fiber.new do
puts "First"
Fiber.yield
puts "Second"
end
fiber.resume # "Fisrt"
fiber.resume # "Second"
fiber.resume # FiberError
Fiberには引数と戻り値がある。Fiber#resumeの引数は、ブロック引数としてFiber内部の処理に渡される。またFiber.yieldの引数は、Fiber#resumeの戻り値となる。指定した値まで整数を順に返すジェネレータを実装してみると以下のようになる。
fiber = Fiber.new do |num|
num.times do |i|
Fiber.yield i
end
end
p fiber.resume 3 # 0
p fiber.resume # 1
p fiber.resume # 2
p fiber.resume # 3
p fiber.resume # FiberError
