From: Yusuke ENDOH Date: 2011-01-25T22:09:17+09:00 Subject: [ruby-dev:43106] Re: pthread_cond を用いたConditionVariable 遠藤です。 2011年1月25日17:50 KOSAKI Motohiro : >> の部分は、native_mutex_lock の直前に別スレッドで CV#signal が呼ばれたとき、 >> signal が無視される気がしました (気のせいかもしれませんが) 。 >> *snip* > ええと、いままではGVL持ってるときは他のロックとるの禁止にしてますよね。 > GVLスレッドが待ってしまうと、全部止まるから。 mutex->lock とかは GVL 持ってる時にロックしてますが、そういう話 ではない? > 若干危険な香りがします。 うーん。危険かなあ。 確かに自信はないんですが、どう直せばいいでしょうね。 それとも signal 漏れしそうなのは私の気のせい? >> 2 は、CV#wait は return したときに時に引数の mutex をロックしていることが >> 期待されていますが、非同期例外が投げ込まれたら即座に終了することも期待され >> ていて、どっちを優先すべきか自明でないという設計上の悩みです。 >> 個人的には、完全に割り込めないのは kill -9 でしか止められなくて困るので、 >> 非同期例外を優先すべきだと思っています。 > > わたしは逆で、mutexロック待ちになるってのはCV#signalがわがmutexを離さないという > 状況なんですが、実際にはそんな事しないと思います。まあデバッグ中はミスるかもしれませんが Ctrl-C を頻繁にしたい状況なので、デバッグ中がメインです。 mutex を離さないバグは、CV#signal 周りよりはむしろ、他スレッドの CV#wait の周りでやりがちな気がします。例えば、 m.synchronize do cv.wait while predicate # ここで無限ループ、またはとても時間がかる end とか。 私が Ruby を好きな理由は、Kernel#p を始め、デバッグが軽快で楽しく なるようにしているところなので、この程度のことで kill -9 が必要に なるのは嫌です。 >> CV 以外のわかりやすい Ruby 向けの同期プリミティブはないですかねえ。例えば >> predicate をブロックに包むだけでも大分わかりやすくなるのではないか。 > > ブロックを提供するのには賛成です。 こんな感じですかねえ。 class SynchronizedQueue def initialize @array = [] @cv = ConditionVariable.new { !@array.empty? } end def push(x) @cv.signal_and_synchronize { @array << x } end def pop @cv.wait_and_synchronize { @array.unshift } end end >> さらに、CV の API は C API (pthread) のパクリなので、C に存在しない機能 >> (例外など) との兼ね合いが検討されていないという問題もあります。 >> 仮に 1 の機能が整備されたとしても、Ctrl-C まで考慮した CV#wait の使い方は >> かなりややこしくなり、常人には正しく使いこなせない予感がします。 > > ぜんぜんドキュメントに注意点が書いてないんですよね。 そもそも、注意点を網羅的かつ明確に理解できている人が現時点で存在 しないという説。 >> いずれも、CV を C 実装に直すだけでどうにかなる話ではないと思います。 > > 意図は、1.9.x は非同期例外時にmutexをlockしてる事を保証することでごまかして、 > 非同期例外の抜本的な拡張は2.0送りじゃないか。というものでした。 > また、2.0ではCVに変わる代替APIの検討がいるかと思います。 設計の問題に関しては、1.9.x は現状のまま、に一票。 パフォーマンス改善のために C 化することについては、安定させるのが 大変そうだけどそれに見合うかなーという疑問を除けば、賛成でも反対 でもないです。 -- Yusuke Endoh