From: KOSAKI Motohiro Date: 2011-01-25T17:50:28+09:00 Subject: [ruby-dev:43101] Re: pthread_cond を用いたConditionVariable > こういうのは安定させるのが大変そうですね。 > パッチ眺めただけで申し訳ないんですが、 > > + BLOCKING_REGION_CORE({ > + native_mutex_lock(&arg->cv->lock); > + th->transition_for_lock = 0; > + native_cond_wait(&arg->cv->cond, &arg->cv->lock); > + th->transition_for_lock = 1; > + native_mutex_unlock(&arg->cv->lock); > + }); > > の部分は、native_mutex_lock の直前に別スレッドで CV#signal が呼ばれたとき、 > signal が無視される気がしました (気のせいかもしれませんが) 。 > > + native_mutex_lock(&arg->cv->lock); > + BLOCKING_REGION_CORE({ > + th->transition_for_lock = 0; > + native_cond_wait(&arg->cv->cond, &arg->cv->lock); > + th->transition_for_lock = 1; > + }); > + native_mutex_unlock(&arg->cv->lock); > > とすればいい、のかなあ。 ええと、いままではGVL持ってるときは他のロックとるの禁止にしてますよね。 GVLスレッドが待ってしまうと、全部止まるから。 若干危険な香りがします。 >> パフォーマンスはさておくとしても、今のCVはCtrl-Cセーフじゃないというかなり致命的な弱点があるので >> いつかはC実装に直さないといけないという認識でした。すばらしいです。 > > C 実装にすることはあまり関係ないんじゃないでしょうか。 > > CV + Ctrl-C に関しては、以下の 3 つの設計上の問題に分けられると思います。 > > 1. 言語レベルで非同期例外に対する機能が不足している > 2. CV#wait に非同期例外が投げ込まれたとき、どうすればいいかわからない > 3. CV#wait の API が難しすぎる > > 1 は、ensure 節で Ctrl-C が起きたら後処理できない、という有名な問題です。 > このあたりの機能がちゃんと整備されれば、Ruby 実装でも Ctrl-C 安全な CV は > 作れると思います。 それはそうなんでしょうが。1.9.xでensureのセマンティクスを変えるってのは 議論の余地があるでしょうね。 > 2 は、CV#wait は return したときに時に引数の mutex をロックしていることが > 期待されていますが、非同期例外が投げ込まれたら即座に終了することも期待され > ていて、どっちを優先すべきか自明でないという設計上の悩みです。 > 個人的には、完全に割り込めないのは kill -9 でしか止められなくて困るので、 > 非同期例外を優先すべきだと思っています。 わたしは逆で、mutexロック待ちになるってのはCV#signalがわがmutexを離さないという 状況なんですが、実際にはそんな事しないと思います。まあデバッグ中はミスるかもしれませんが そのときに kill を要求するのは、そんなに理不尽じゃないと思います。 CV#waitにオプションがあって選べてもいいと思いますが。 また、将来的にはもっと高レベルな排他APIを用意して移行を促していくのが正しいのでしょう。 APIセマンティクス的に間違えやすくて使いにくいというのはどうしようもない面があるので 今のAPIで実装でだけ努力しても、どうやっても誰かがうれしくない状況は避けられなさそうです。 > 3 は、CV#wait の API は (一見簡単ですが) 細かい使用上の注意があり、しかも > それが十分に周知されていないという問題です。 > 「必ず while で包め」とか、同じ CV に対応する predicate は全スレッドで同じ > でないといけない (はず、私の勘違いの可能性も) とか、timeout が入るとさらに > 難しくなる ([ruby-dev:41255]) とか、そもそも CV#wait の timeout には race > condition があるとか。 > CV 以外のわかりやすい Ruby 向けの同期プリミティブはないですかねえ。例えば > predicate をブロックに包むだけでも大分わかりやすくなるのではないか。 ブロックを提供するのには賛成です。 > さらに、CV の API は C API (pthread) のパクリなので、C に存在しない機能 > (例外など) との兼ね合いが検討されていないという問題もあります。 > 仮に 1 の機能が整備されたとしても、Ctrl-C まで考慮した CV#wait の使い方は > かなりややこしくなり、常人には正しく使いこなせない予感がします。 ぜんぜんドキュメントに注意点が書いてないんですよね。 > いずれも、CV を C 実装に直すだけでどうにかなる話ではないと思います。 意図は、1.9.x は非同期例外時にmutexをlockしてる事を保証することでごまかして、 非同期例外の抜本的な拡張は2.0送りじゃないか。というものでした。 また、2.0ではCVに変わる代替APIの検討がいるかと思います。 >> 今のRubyだとdeadlockするのが正しい挙動のときに assert(deadlockすること) と書く方法がない気がするのですが >> この認識はあってますかね? > > Ruby を別プロセスを立ち上げて、その中で deadlock を起こさせ、標準 > エラー出力に例外が出てくることを見る感じでどうでしょう。 やっぱりそれですかね。