summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/thread.rb49
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