原です。

せきさん、お世話になっています。まだ erb.rb とスレッドの絡む話
についていっていません。(すいません、引越しで忙しくて。(^^;)

In message "[ruby-list:14445] Re: ConditionVariable (thread.rb)"
    on 99/05/24, SEKI <m_seki / mva.biglobe.ne.jp> writes:
|
|咳です。
|
|:ConditionVariable のwaitメソッドの引数 mutex は
|:どう使えばよいのでしょうか?
|:なにかサンプルスクリプトはないでしょうか?
|
|こんな感じでしょうか?

|class TinyQueue

これ、いいと思います。

# synchronize を使わないのは何か理由があるんですか?

前に、ほぼ同様なものを [ruby-list:6794] に前田さんが書いて
います。当時の ConditionVariable の仕様はちょっと違いますが。

[ruby-list:6735] から始まるスレッドは読み難くてというか、そ
もそもスレッドって難しくて往生します。

ConditionVariable#wait(mutex) ってのも分かりにくいですね。
この mutex ってロックするために渡すのではなく、一時的に解
放してもらうためにあるんですね。

ところでなんでこんな仕様になっているんですかね。そもそも
wait とか stop とかは dead lock になる可能性があるので、
必ず注意が必要なのだから、むしろその部分はユーザーまかせ
ていいのではないでしょうか。わざわざ指定するのは注意の喚
起のため?

こういう案はどうでしょうか。

Mutex に一時的なロックの解除するメソッドを指定する。

  class Mutex
    def release
      unlock
      yield
      lock
    end
  end

で、ConditionVariable#wait の引数はなし(あるいはオプション)にする。

  class ConditionVariable
    def wait
      @waiters_mutex.synchronize {
        @waiters.push(Thread.current)
      }
      Thread.stop
    end
  end

で、こうすると

  def enq(v)
    @mutex.synchronize {
      @full.wait(@mutex) if count == @max 
      @q.push v
      @empty.signal if count == 1 
    }
  end

と書く所を

  def enq(v)
    @mutex.synchronize {
      @mutex.release {
	@full.wait if count == @max
      }
      @q.push v
      @empty.signal if count == 1 
    }
  end

と書くようになる。

この方が何をしているか、どんな危険があるかはっきりして見通
しがよくなりますよね。wait を synchronize の外に出しても同
値であることなどが見えるし。