Allow to unlock mutex locked by another thread

Issue #3251 has been updated by kosaki (Motohiro KOSAKI).

1)まず元々の提案は非同期例外を救うというモチベーションから来ているので、専用構文のほうがベターであろう。よってたぶんmutexの変更は不要
2)やるなら、semaphoeをつくるほうがいいなあ

Feature #3251: allow to unlock mutex locked by another thread

Author: mame (Yusuke E.)
Status: Assigned
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: 2.0.0

=begin
遠藤です。

現状では mutex は lock したスレッドからしか unlock できませんが、
これを許可するようにしませんか。動機は 2 つあります。

  1. Python の condition variable が mutex を別スレッドから unlock
    することで実装されている、のが真似できる
  2. Thread#raise を race condition なしに使えるようになる (気がする)

1 について、Python の condition variable は以下のような感じに実装
されています。

def wait(m1)
m2 = Mutex.new
m2.lock
@waiters << m2
m1.unlock
begin
m2.lock
ensure
m1.lock
end
end

def signal
@waiters.shift.unlock
end

つまり、wait は二重に mutex を lock しようとすることでブロックし、
signal は mutex を別スレッドから unlock することでブロックしている
スレッドを再開します。
今の ConditionVariable の実装には大量の問題点が指摘されているので、
Python の真似をするとよいのではと思います。

権威主義

2 について、現状は Thread#raise には以下のような race が存在します。

t1: begin 節を実行している
t2: t1.raise する
t1: rescue/ensure 節の実行を開始する
t3: t1.raise する
t1: rescue/ensure 節が実行されないまま再度例外が発生する

ちなみにこの race はシグナルにも存在します

これを、Thread#raise の前に Mutex#lock するというルールにすれば、
race を避けて使うことができるようになります。と思います。

t1: begin 節を実行している
t2: m.lock; t1.raise する
t1: rescue/ensure 節の実行を開始する
t3: m.lock が止まらないので t1.raise できない
t1: 次の例外が投げ込まれる準備ができたら m.unlock する
t3: m.lock が終わって t1.raise する


Yusuke E. [email protected]
=end