diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/thread.rb | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/lib/thread.rb b/lib/thread.rb index 936768fa9b..baa248e927 100644 --- a/lib/thread.rb +++ b/lib/thread.rb @@ -17,6 +17,16 @@ if $DEBUG Thread.abort_on_exception = true end +def Thread.exclusive + begin + Thread.critical = true + r = yield + ensure + Thread.critical = false + end + r +end + class Mutex def initialize @waiting = [] @@ -68,39 +78,46 @@ class Mutex unlock end end + + def exclusive_unlock + return unless @locked + Thread.exclusive do + t = @waiting.shift + @locked = false + t.wakeup if t + yield + end + self + end end class ConditionVariable def initialize @waiters = [] - @waiters_mutex = Mutex.new - @waiters.taint # enable tainted comunication - self.taint end def wait(mutex) - mutex.unlock - @waiters_mutex.synchronize { + mutex.exclusive_unlock do @waiters.push(Thread.current) - } - Thread.stop + Thread.stop + end mutex.lock end def signal - @waiters_mutex.synchronize { - t = @waiters.shift - t.run if t - } + t = @waiters.shift + t.run if t end def broadcast - @waiters_mutex.synchronize { - for t in @waiters - t.run - end + waitors0 = nil + Thread.exclusive do + waiters0 = @waitors.dup @waiters.clear - } + end + for t in waiters0 + t.run + end end end |