2016-06-01 6 views
0

私は2つのFibersを使って基本的な歩留まり/再開パターンを検証しようとしています。しかし、yield/resumeメカニズムは機能していないようです。私はいくつかのバリエーションを試しましたが、間違いを見つけることはできません。ファイバーとの単純な並列性?

イベントの

期待されるシーケンス:スレッドオフ

  1. キック(時間0)
  2. 最初に戻るまで待機(時間+ 2秒)第二戻るまで
  3. 待機(時間+ 2秒)
  4. 済(時間> + 3秒)

は#1

をお試しください
#!/usr/bin/env ruby 

require 'fiber' 

f1 = Fiber.new do 
    puts "Fiber1 starting @ #{Time.new}." 
    fib1 = Fiber.current 
    Fiber.yield 
    sleep 2 
    puts "Fiber1 done @ #{Time.new}." 
    fib1.resume(1) 
end 
f2 = Fiber.new do 
    puts "Fiber2 starting @ #{Time.new}." 
    fib2 = Fiber.current 
    Fiber.yield 
    sleep 2 
    puts "Fiber2 done @ #{Time.new}." 
    fib2.resume(2) 
end 

puts "Waiting @ #{Time.new}." 
r1 = f1.resume 
puts "f1 back @ #{Time.new} - #{r1}." 
r2 = f2.resume 
puts "f2 back @ #{Time.new} - #{r2}." 

sleep 1 
puts "Done @ #{Time.now}." 

これがもたらす:FiberErrorでresume結果第二の追加

Waiting @ 2016-06-01 06:15:52 -0700. 
Fiber1 starting @ 2016-06-01 06:15:52 -0700. 
f1 back @ 2016-06-01 06:15:52 -0700 - . 
Fiber2 starting @ 2016-06-01 06:15:52 -0700. 
f2 back @ 2016-06-01 06:15:52 -0700 - . 
Done @ 2016-06-01 06:15:53 -0700. 

これは、その結果#2

#!/usr/bin/env ruby 

require 'fiber' 

f1 = Fiber.new do 
    puts "Fiber1 starting @ #{Time.new}." 
    Fiber.yield 
    sleep 2 
    puts "Fiber1 done @ #{Time.new}." 
    1 
end 
f2 = Fiber.new do 
    puts "Fiber2 starting @ #{Time.new}." 
    Fiber.yield 
    sleep 2 
    puts "Fiber2 done @ #{Time.new}." 
    2 
end 

puts "Waiting @ #{Time.new}." 
r1 = f1.resume 
puts "f1 back @ #{Time.new} - #{r1}." 
r2 = f2.resume 
puts "f2 back @ #{Time.new} - #{r2}." 

sleep 1 
puts "Done @ #{Time.now}." 

を試してみてください。どちらの場合も

Waiting @ 2016-06-01 10:53:17 -0700. 
Fiber1 starting @ 2016-06-01 10:53:17 -0700. 
f1 back @ 2016-06-01 10:53:17 -0700 - . 
Fiber2 starting @ 2016-06-01 10:53:17 -0700. 
f2 back @ 2016-06-01 10:53:17 -0700 - . 
Done @ 2016-06-01 10:53:18 -0700. 

、開始/終了時刻が同じであると返されない結果。

+0

あなたの繊維が自分自身でレジュームを呼び出しているのはなぜですか? –

+0

@FrederickCheung - Fiber.current.resumeを使わずに試してみました。それでも、1)スレッドを開始し、2)最初に戻るまで待機し、3)2回目の戻りまで待機し、4)完了したという期待される結果をもたらさない。 – saarp

答えて

1

繊維自体は、少なくとも、イベントマシンのフレームワークなどのコールバックメカニズムを使用しないと、並列性を達成できません。

あなたが書いたのは、単純にコードブロック間で同期実行をインターリーブしようとしていることです。予想されるシーケンスが得られない理由は、キックオフをシミュレートしている間に、あなたは焼き後にファイバーを再開しなかったからです。

あなたは終わりに便利、特にたとえば、次の記事を見つけるかもしれない:
http://schmurfy.github.io/2011/09/25/on_fibers_and_threads.html

相互に制御を移す繊維示すもう一つの例:
https://gist.github.com/aprescott/971008

これは、あなたが結果を期待与える必要が:

#!/usr/bin/env ruby 

require 'fiber' 

f1 = Fiber.new do 
    puts "Fiber1 starting @ #{Time.new}." 
    Fiber.yield 
    sleep 2 
    puts "Fiber1 done @ #{Time.new}." 
    1 
end 
f2 = Fiber.new do 
    puts "Fiber2 starting @ #{Time.new}." 
    Fiber.yield 
    sleep 2 
    puts "Fiber2 done @ #{Time.new}." 
    2 
end 

puts "Waiting @ #{Time.new}." 
r1 = f1.resume 
puts "f1 back @ #{Time.new} - #{r1}." 
r2 = f2.resume 
puts "f2 back @ #{Time.new} - #{r2}." 

# Resume right after the yield in the fiber block and 
# execute until it encounters another yield or the block ends. 
puts "Resuming f1" 
f1.resume 
puts "Resuming f2" 
f2.resume 

sleep 1 
puts "Done @ #{Time.now}." 

出力:

Waiting @ 2016-06-05 00:35:29 -0700. 
Fiber1 starting @ 2016-06-05 00:35:29 -0700. 
f1 back @ 2016-06-05 00:35:29 -0700 - . 
Fiber2 starting @ 2016-06-05 00:35:29 -0700. 
f2 back @ 2016-06-05 00:35:29 -0700 - . 
Resuming f1 
Fiber1 done @ 2016-06-05 00:35:31 -0700. 
Resuming f2 
Fiber2 done @ 2016-06-05 00:35:33 -0700. 
Done @ 2016-06-05 00:35:34 -0700. 
+0

ありがとう、@vaibhav。 'sleep'は実際にはEM :: Synchrony.syncを使用して直列化された2つのDefferable結果の呼び出しに置き換えられるため、並列実行の側面を処理する必要があると思います。私はまだそれを確認する必要があります。 – saarp