Thread を使って Fiber を模倣するライブラリを作ってみました。
require "threadfiber" ThreadFiber.deploy f = Fiber.new do p :foo Fiber.yield p :bar end f.resume #=> :foo p :hoge #=> :hoge f.resume #=> :bar
1.9 の Fiber とちがって、Thread をまたいで Fiber が呼べます。
require "threadfiber" ThreadFiber.deploy f = Fiber.new do p :foo Fiber.yield p :bar end Thread.new { f.resume }.join #=> :foo Thread.new { f.resume }.join #=> :bar
ただし複数のスレッドから同時に ThreadFiber#resume したら、片方に double resume (FiberError) が投げられます。ThreadFiber#resume_wait を使えば、その Fiber が yield されるまで待ちます。
1.8 でも動きます。1.8 で Fiber を試してみたい人にはいいかも。まあ僕は普段 1.9 しか使ってないので、知らないうちに動かなくなるかも知らないですけど。
$ ruby18 -v -e ' require "rubygems" require "threadfiber" ThreadFiber.new { p :foo }.resume ' ruby 1.8.7 (2008-08-21 revision 18749) [i686-linux] :foo
他に 1.9 の Fiber との違いは、
- 遅い (1.9 の Fiber も速くはないけど、それよりも遅い)
- Fiber#transfer がない (たぶんすぐ作れるけど、要らないと思うので)
- root fiber では Fiber.current が nil を返す (面倒だった)
- fiber の中と外でスレッド変数のスコープがちがう
くらいです。たぶん。
ソースはこちら。はじめての github 。
gem も公開してみたので、以下でインストールできるかもしれません。どうなっても知りませんけど。
$ gem install mame-threadfiber --source=http://gems.github.com $ ruby -e ' require "rubygems" require "threadfiber" ThreadFiber.new { p :foo }.resume ' :foo
ちなみに 1.8 で test/test_threadfiber.rb を動かすと SEGV しますが、threadfiber は pure Ruby なので、どうみても 1.8 のバグです。callcc と thread と gc の絡んだ問題っぽくてデバッグしたくないので、見なかったことに。