2 # thread.rb - thread support classes
3 # by Yukihiro Matsumoto <matz@netlab.co.jp>
5 # Copyright (C) 2001 Yukihiro Matsumoto
6 # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
7 # Copyright (C) 2000 Information-technology Promotion Agency, Japan
10 unless defined? Thread
11 raise "Thread not available for this ruby interpreter"
14 unless defined? ThreadError
15 class ThreadError < StandardError
20 Thread.abort_on_exception = true
24 # ConditionVariable objects augment class Mutex. Using condition variables,
25 # it is possible to suspend while in the middle of a critical section until a
26 # resource becomes available.
33 # resource = ConditionVariable.new
37 # # Thread 'a' now needs the resource
38 # resource.wait(mutex)
39 # # 'a' can now have the resource
45 # # Thread 'b' has finished using the resource
50 class ConditionVariable
52 # Creates a new ConditionVariable
56 @waiters_mutex = Mutex.new
60 # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
64 # TODO: mutex should not be used
65 @waiters_mutex.synchronize do
66 @waiters.push(Thread.current)
73 # Wakes up the first thread in line waiting for this lock.
77 t = @waiters_mutex.synchronize { @waiters.shift }
85 # Wakes up all threads waiting for this lock.
90 @waiters_mutex.synchronize do
91 waiters0 = @waiters.dup
104 # This class provides a way to synchronize communication between threads.
112 # producer = Thread.new do
114 # sleep rand(i) # simulate expense
116 # puts "#{i} produced"
120 # consumer = Thread.new do
123 # sleep rand(i/2) # simulate expense
124 # puts "consumed #{value}"
132 # Creates a new queue.
137 @que.taint # enable tainted comunication
144 # Pushes +obj+ to the queue.
174 # Retrieves data from the queue. If the queue is empty, the calling thread is
175 # suspended until data is pushed onto the queue. If +non_block+ is true, the
176 # thread isn't suspended, and an exception is raised.
178 def pop(non_block=false)
182 raise ThreadError, "queue empty" if non_block
183 @waiting.push Thread.current
203 # Returns +true+ if the queue is empty.
210 # Removes all objects from the queue.
217 # Returns the length of the queue.
229 # Returns the number of threads waiting on the queue.
237 # This class represents queues of specified size capacity. The push operation
238 # may be blocked if the capacity is full.
240 # See Queue for an example of how a SizedQueue works.
242 class SizedQueue < Queue
244 # Creates a fixed-length queue with a maximum size of +max+.
247 raise ArgumentError, "queue size must be positive" unless max > 0
250 @queue_wait.taint # enable tainted comunication
255 # Returns the maximum size of the queue.
262 # Sets the maximum size of the queue.
277 t = @queue_wait.shift
288 # Pushes +obj+ to the queue. If there is no space left in the queue, waits
289 # until space becomes available.
295 break if @que.length <= @max
296 @queue_wait.push Thread.current
326 # Retrieves data from the queue and runs a waiting thread, if any.
332 if @que.length < @max
334 t = @queue_wait.shift
359 # Returns the number of threads waiting on the queue.
362 @waiting.size + @queue_wait.size
366 # Documentation comments:
367 # - How do you make RDoc inherit documentation from superclass?