From: Yusuke ENDOH Date: 2007-08-22T21:45:40+09:00 Subject: [ruby-dev:31596] Re: Fiber reviesed 遠藤です。 > いろいろと Fiber の仕様を悩んでいたんですが,決めました.で,実装 > してコミットしました. お疲れ様です。面白いものをありがとうございます。 さっそく遊んでみたのですが、残念ながらコルーチンとセミコルーチンは 相性が悪いことに気がついてしまいました。 Fiber の中で Fiber::Core を終わらせると、その時点で実行中だった Fiber が「生きながら永遠に実行されない?」状態になります。 f = Fiber.new do Fiber::Core.new { }.transfer p 1 # ここは永遠に実行されない? end f.resume f.transfer f.resume #=> double resume (FiberError) 要するに、「Fiber をネストしたら変なことになる」という問題が「Fiber の 中で Fiber::Core を使うと変なことになる」に変わったようです。 例えば Generator の中で Fiber::Core に transfer すると、Generator から next を取ろうとするしたとき変なことになります。 def (o = Object.new).foo yield 1 yield 2 yield 3 Fiber::Core.new { }.transfer end g = o.to_enum(:foo) p g.next #=> 1 p g.next #=> 2 p g.next #=> nil (?) p g.next #=> double resume (FiberError) (??) 解決の方針をいくつか考えてみました。 - Fiber::Core をなくす - Fiber::Core の終了時の戻り先を root fiber 以外にする (じゃあどこ?) - Fiber::Core を呼び出せるのは root fiber だけ、にする (不便そう) - Fiber::Core は callcc 並の黒魔術である、とレッテルを貼って使わせない 名称については、私は Fiber のままでもいいと思います。 Fiber や Coroutine という言葉には、ちゃんとした定義もコンセンサスも ないようなので、はっきりいって言ったもん勝ちです。 Lua だって自分たちで "Semi"-coroutine と認めているものと Coroutine と 呼んでるわけですし。 だから短くてかっこいいのを選べばいいと思います。 おまけ。以下で落ちました。継続が呼び出せてる時点で何か間違い? i = 0 callcc {|c| $c = c } raise if i == 2 i += 1 Fiber::Core.new { $c.call }.transfer -- Yusuke ENDOH