summaryrefslogtreecommitdiff
path: root/lib/thread.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/thread.rb')
-rw-r--r--lib/thread.rb131
1 files changed, 111 insertions, 20 deletions
diff --git a/lib/thread.rb b/lib/thread.rb
index 4f294cc9a3..91c588f603 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -13,10 +13,14 @@ unless defined? ThreadError
end
end
+if $DEBUG
+ Thread.abort_on_exception = true
+end
+
class Mutex
def initialize
@waiting = []
- @locked = FALSE;
+ @locked = false;
end
def locked?
@@ -24,36 +28,33 @@ class Mutex
end
def try_lock
- result = FALSE
- Thread.critical = TRUE
+ result = false
+ Thread.critical = true
unless @locked
- @locked = TRUE
- result = TRUE
+ @locked = true
+ result = true
end
- Thread.critical = FALSE
+ Thread.critical = false
result
end
def lock
- while (Thread.critical = TRUE; @locked)
+ while (Thread.critical = true; @locked)
@waiting.push Thread.current
Thread.stop
end
- @locked = TRUE
- Thread.critical = FALSE
+ @locked = true
+ Thread.critical = false
self
end
def unlock
return unless @locked
Thread.critical = TRUE
- wait = @waiting
- @waiting = []
+ t = @waiting.shift
@locked = FALSE
Thread.critical = FALSE
- for w in wait
- w.run
- end
+ t.run if t
self
end
@@ -67,6 +68,38 @@ class Mutex
end
end
+class ConditionVariable
+ def initialize
+ @waiters = []
+ @waiters_mutex = Mutex.new
+ end
+
+ def wait(mutex)
+ mutex.unlock
+ @waiters_mutex.synchronize {
+ @waiters.push(Thread.current)
+ }
+ Thread.stop
+ mutex.lock
+ end
+
+ def signal
+ @waiters_mutex.synchronize {
+ t = @waiters.shift
+ t.run if t
+ }
+ end
+
+ def broadcast
+ @waiters_mutex.synchronize {
+ for t in @waiters
+ t.run
+ end
+ @waiters.clear
+ }
+ end
+end
+
class Queue
def initialize
@que = []
@@ -74,20 +107,20 @@ class Queue
end
def push(obj)
- Thread.critical = TRUE
+ Thread.critical = true
@que.push obj
t = @waiting.shift
- Thread.critical = FALSE
+ Thread.critical = false
t.run if t
end
- def pop non_block=FALSE
+ def pop non_block=false
item = nil
until item
- Thread.critical = TRUE
+ Thread.critical = true
if @que.length == 0
if non_block
- Thread.critical = FALSE
+ Thread.critical = false
raise ThreadError, "queue empty"
end
@waiting.push Thread.current
@@ -96,7 +129,7 @@ class Queue
item = @que.shift
end
end
- Thread.critical = FALSE
+ Thread.critical = false
item
end
@@ -107,4 +140,62 @@ class Queue
def length
@que.length
end
+ alias size length
+
+
+ def num_waiting
+ @waiting.size
+ end
+end
+
+class SizedQueue<Queue
+ def initialize(max)
+ @max = max
+ @queue_wait = []
+ super()
+ end
+
+ def max
+ @max
+ end
+
+ def max=(max)
+ Thread.critical = TRUE
+ if @max >= max
+ @max = max
+ Thread.critical = FALSE
+ else
+ diff = max - @max
+ @max = max
+ Thread.critical = FALSE
+ diff.times do
+ t = @queue_wait.shift
+ t.run if t
+ end
+ end
+ max
+ end
+
+ def push(obj)
+ Thread.critical = true
+ while @que.length >= @max
+ @queue_wait.push Thread.current
+ Thread.stop
+ Thread.critical = true
+ end
+ super
+ end
+
+ def pop(*args)
+ Thread.critical = true
+ if @que.length < @max
+ t = @queue_wait.shift
+ t.run if t
+ end
+ super
+ end
+
+ def num_waiting
+ @waiting.size + @queue_wait.size
+ end
end