まつもと ゆきひろです

In message "[ruby-list:6293] external iterator (Re: i++)"
    on 98/02/05, Yukihiro Matsumoto <matz / netlab.co.jp> writes:

|Threadと組み合わせたりすると汎用の外部イテレータが定義できる
|かも知れません.

こういう感じで作ってみました.SizedQueueは標準ライブラリに追
加してもよいな.

require 'thread'

class SizedQueue<Queue
  def initialize(max)
    @max = max
    @queue_wait = []
    super()
  end

  def push(obj)
    while @que.length >= @max
      @queue_wait.push Thread.current
      Thread.stop
    end
    super
  end

  def pop(*args)
    if @que.length < @max
      t = @queue_wait.shift
      t.run if t
    end
    pop = super
    pop
  end
end

class ExternalIterator
  def initialize(ary)
    @ary = ary
    first
  end
  def first
    if @thread
      @thread.exit
    end
    @que = SizedQueue.new(1)
    @more = true
    @thread = Thread.start {
      for i in @ary
	@que.push i
      end
      @more = false;
    }
  end
  def succ
    @que.pop
  end
  def more
    @que.length != 0 or @more
  end
  def each
    @ary.each{|x| yield x}
  end
end