咳です。

From: Shin-ichiro Hara <sinara / blade.nagaokaut.ac.jp>

> これの callcc 版を考えてみました。まず、Queue 相当のものなんですが、
> バッファがないのでかわいらしく Hole という名前にしました。

いまさら Thread 版を作ってみました。

以前に Thread 間 pipe が欲しくて作ったものに手を加えました。
Pipeクラスは原さんのHoleに相当します。

要素に nil を持てるように番兵 (PipeEOF) を導入しています。
また、複数の Thread が pipe に read/write できます。
## イテレータとは関係ないっすね。最初はLinda みたいの作りたかったんです。

Pipe は次のように使います。

pipe = Pipe.new
Thread.new do 
  for i in 1..5
    pipe.write(i)
  end
  pipe.close
end

while (v = pipe.read) != pipe.eof
  p v
end    

以下は、Pipe と 外部イテレータです。

-- pipe.rb --
#!/usr/local/bin/ruby

require 'thread'

class PipeEOF; end
class PipeBrokenError<RuntimeError; end

class Pipe
  def initialize(pipelen=1)
    @enq = Queue.new
    @buffer = Queue.new
    for i in 1..pipelen
      @enq.push nil
    end
    @eof = PipeEOF.new		# sentinel
    @done = false
  end
  attr :eof

  def eof?(e)
    @eof == e
  end

  def write(e)
    @enq.pop
    if @done
      @enq.push nil
      raise(PipeBrokenError, 'closed') 
    end
    @buffer.push(e)
  end

  def read
    begin
      v = @buffer.pop
    ensure
      @enq.push nil
      @buffer.push(@eof) if (v == @eof)
    end
  end

  def close
    @buffer.push(@eof)
    @done = true
  end
end

#=begin
#
# 外部イテレータにしてみた部分
#

if __FILE__ == $0
  class Pipe
    def externalIterator(src)
      src = src
      que = Pipe.new
      Thread.new do
	for i in src
	  que.write(i)
	end
	que.close
      end
      que
    end
    module_function :externalIterator
  end
  
  def match_items(a, b)
    begin
      ia = Pipe.externalIterator(a)
      ib = Pipe.externalIterator(b)
      i = 0
      loop do
	item_a = ia.read
	item_b = ib.read
	
	if ia.eof == item_a and ib.eof != item_b
	  printf "collections `a' shorter than `b'(size %d)\n", i
	  return
	elsif ia.eof != item_a and ib.eof == item_b
	  printf "collections `b' shorter than `a'(size %d)\n", i
	  return
	elsif ia.eof == item_a and ib.eof ==item_b
	  break
	elsif item_a != item_b
	  printf "collections differ on %dth item\n", i
	  return
	end
	i+=1
      end
      printf "collections `a' and `b' are same(size %d)\n", i
    ensure
      ia.close
      ib.close
    end
  end
  
  match_items([1,2,3,4,5],[1,2,8,9,0])
  match_items([1,2,3,4],[1,2])
  match_items([1,2],[1,2,8,9,0])
  match_items([1,2],[1,2,8,9,0])
  match_items([1,2,3,4,5],[1,2,3,4,5])
  match_items([1,2,3,4,5],[1,2,3,4,4])
  match_items({1,2,3,4},{1,2,3,4})
  match_items([1,2,3,nil,5],[1,2,3,nil,5])
end  
#=end
=begin
#
# Pipe のテストプログラム部分
#

if __FILE__ == $0
  pipe = Pipe.new(3)

  writer = []
  for i in 1..4 
    th = Thread.new {
      for e in 1..5 
	pipe.write(e)
      end
    }
    writer.push(th)
  end

  reader = []
  for i in 1..4
    th = Thread.new {
      begin
	while (v = pipe.read) != pipe.eof
	  p v
	end
      ensure
	print "died\n"
      end
    }
    reader.push(th)
  end

  begin
    writer.each do |th|
      Thread.join(th)
    end
    pipe.close
  end

  reader.each do |th|
    Thread.join(th)
  end
end
=end