Fiberとは
Fiberを利用することで複数のプログラム間で実行の中断や再開を相互に行わせることができます。
Fiberを用いると「ある処理を途中まで実行して、その後任意のタイミングで、前回の続きから処理を行う」みたいな処理の流れを扱うことが出来ます!
基本的な使い方
Fiberの作成
生成されたファイバは、Fiber#resume
メソッドにより実行を開始する必要があります。
ファイバの切り替えは自動的に行われないので、自分で切り替える必要があります。
fiber = Fiber.new {
puts 'Hello, Fiber!'
# 実行されたファイバから親に切り替える
Fiber.yield
puts 'Hello, (again)'
}
fiber.resume #=> "Hello, Fiber!"
fiber.resume #=> "Hello, (again)"
fiber.resume #=> FiberError: dead fiber called
引数と戻り値について
fiber = Fiber.new {|first|
puts 'Hello, Fiber!'
second = Fiber.yield('goodbye')
puts second
puts 'Hello, (again)'
}
puts fiber.resume('Hello, Fiber!') #=> "Hello, Fiber!"
puts fiber.resume(Hello, (again)) #=> "goodbye", "Hello, (agein)", "goodbye, (again)"
ジェネレーター
ジェネレーターとは、部分的な結果だけを計算して返し、続きを次回に計算すること
です。
これにより、実際の計算を最小限で済ませて、大きいデータを少ないリソースで扱うことが出来ます。
fiber = Fiber.new {
a, b = 0, 1
loop do
a, b = b, a + b
Fiber.yield(a)
end
}
10.times.map { fiber.resume } #=> [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
puts fiber.resume #=> "89"
puts feiber.resume #=> "144"
標準添付ライブラリを利用してより手軽に!
標準添付ライブラリでは、親子関係のないコルーチンとして扱うことが出来ます。
新たにFiber#transfer
使えるようになるメソッドになります。
このメソッドは、ファイバの処理を移した際に、その後自動的に呼び出し元に戻らないということです。
require 'fiber'
f1 = Fiber.new {
puts 'from f1'
}
f2 = Fiber.new {
f1.transfer
puts 'from f2'
}
# 生成されてからスタートしていないorブロックが終了していないときにtrue
f1.alive? #=> true
f2.resume #=> "from f1"