From: Yusuke ENDOH Date: 2011-01-25T12:38:35+09:00 Subject: [ruby-dev:43098] Re: pthread_cond を用いたConditionVariable 遠藤です。 2011年1月25日3:40 KOSAKI Motohiro : >> POSIX thread の condition variable を直接用いて ConditionVariable を作っ >> てみました. とはいえ, まだまだ完全ではないのですが... 現行の CV もコア部分 (Mutex#sleep) は native_sleep の pthread_cond_wait の はずなんですが、何が違うんでしょうね。細々した部分がRuby 実装部分で Array とかいじってる のが遅いのかなあ。 >> 実装についてですが, Thread等の仕組みが十分に分かっていないので, 私だけ >> では完全なものにするのは難しいです. 良く知っていらっしゃる方々に完全な >> ものにして, Ruby に取り込んでいただければと思っています. こういうのは安定させるのが大変そうですね。 パッチ眺めただけで申し訳ないんですが、 + 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); とすればいい、のかなあ。 > パフォーマンスはさておくとしても、今の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 は 作れると思います。 2 は、CV#wait は return したときに時に引数の mutex をロックしていることが 期待されていますが、非同期例外が投げ込まれたら即座に終了することも期待され ていて、どっちを優先すべきか自明でないという設計上の悩みです。 個人的には、完全に割り込めないのは kill -9 でしか止められなくて困るので、 非同期例外を優先すべきだと思っています。 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 実装に直すだけでどうにかなる話ではないと思います。 > 今のRubyだとdeadlockするのが正しい挙動のときに assert(deadlockすること) と書く方法がない気がするのですが > この認識はあってますかね? Ruby を別プロセスを立ち上げて、その中で deadlock を起こさせ、標準 エラー出力に例外が出てくることを見る感じでどうでしょう。 -- Yusuke Endoh