前田です。

At Sun, 6 Jun 1999 01:20:14 +0900,
Shin-ichiro Hara <sinara / blade.nagaokaut.ac.jp> wrote:
> |> 例えば Thread#run が一つも無くて、Thread#wakeup のみが使われている
> |> こと。これも、スケジューリング問題の調整のためでしょうか。あとロッ
> |> クの owner という概念があって、そこかしこに、owner がずれてると例外
> |> を発生させる様になっているところとか。owner はカウントつきロックの
> |> ためにだけあるのでは無いようですね。
> |
> |[ruby-list:6791]あたりにその辺の理由が書いてあります。
> |簡単に言うとsignal/broadcastされた時点でwaitしたスレッドが優先的
> |にロックを獲得できるようにするためです。
> 
> ええ、そうなっているのはわかります。しかしそんなことが必要になっ
> てしまうのは signal で run させずに wakeup させているからですよ
> ね。私の cv2.rb みたいに run させればいいだけのことではないかな
> あ。なぜ run させずに wakeup & pass させるのだろう。

t.run

というのは、

t.wakeup
Thread.pass

と同値なので、t.runした直後にtに実行権が渡ることは必ずしも保証さ
れないような気がして、このようにしてあります。
# ひょっとして保証されるんですか?>まつもとさん

つまりrunでも問題が起きる可能性はあるのではないかと。

> |あと、wakeupを使っているのはスケジューリングが起こって欲しくない
> |からですね。
> 
> ああ、ここでスケジューリングというのはスレッドのスイッチという意味
> ですね。なぜスイッチしたらいかんのだろう。どうせ不定な時期にスイッ
> チするんだからここで意図してスイッチを起こしてもいいようが気がする
> のですが。

すいません、「スケジューリング」と書いてたのは「スケジューリング
イベント」と書こうとしていたのでした。

で、ここでwakeupしているのは、クリティカルセクションではrunしても
スケジューリングイベントは起きないからです。
# つまり、runでも同じだけど意味がないのでwakeupにしているわけです。

> いや、条件変数の signal が原因でスレッドのスイッチが起こらないよう
> にできるなら、その方が気持ちいいとは思います。たかが変数ごときにス
> ケジュールを変形されたくないという気持ちは分かります。
> 
> もしそういうことなら、signal の頭で Thread.critical の値を保存し
> て、最後にそれを復活させる(そして Thread.pass もさせない)という
> のが徹底していて、いい様な気もします。

いや、ここはスケジューリングイベントを起こさないといけないんです。
というのは、signalしたスレッドがまだロックを保持している間に、
waitしているスレッドにスイッチしておかないと、せっかくキューに優
先順位を設けたのに、キューに並ぶひまもなく、他のスレッドにロック
を奪われてしまうかもしれないからです。
signalしたスレッドがまだロックを保持している間は、他のスレッドに
実行が渡ってもキューの優先順位があるので大丈夫なのですが、ロック
がフリーになってからはじめてスケジューリングイベントが起こったと
すると、他のスレッドにロックを横取りされてしまいます。

で、[ruby-list:6791]でも書いているのですが、さらにsignalしたスレッ
ドから他のスレッドに移ってまた戻ってくる間に必ずwaitしたスレッド
に実行が移る保証があるのか、というのが問題になるんですが、たぶん
少なくとも今の実装では保証されると思います。

> |う、手元のmonitor.rbの253行目はスクリプトの終わりになってます(^_^;
> |なんかこの間バグを一つつぶしたような気がする(夢だったかも)ので
> |ruby-1.3.4付属のもので試していただけませんか?
> 
> おおっ、新しい monitor.rb を見てみました。かなり分かりやすい。いま
> まで難しい、難しいと言っていたのは、ruby-1.2.5 までの話です。なるほ
> ど、組み込みクラスのインスタンスがインスタンス変数を持てる様になっ
> たのは大きいですね!

このおかげでかなり楽になりましたね。

> 時代は 1.3 だな。(^^)

です:-)

-- 
前田 修吾