3 # This file is overwritten by ext/thread/lib/thread.rb unless ruby
4 # is configured with --disable-fastthread.
6 # thread.rb - thread support classes
7 # $Date: 2007-02-12 15:01:19 -0800 (Mon, 12 Feb 2007) $
8 # by Yukihiro Matsumoto <matz@netlab.co.jp>
10 # Copyright (C) 2001 Yukihiro Matsumoto
11 # Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
12 # Copyright (C) 2000 Information-technology Promotion Agency, Japan
15 unless defined? Thread
16 fail "Thread not available for this ruby interpreter"
21 # Wraps a block in Thread.critical, restoring the original value upon exit
22 # from the critical section.
25 _old = Thread.critical
27 Thread.critical = true
30 Thread.critical = _old
36 # Mutex implements a simple semaphore that can be used to coordinate access to
37 # shared data from multiple concurrent threads.
42 # semaphore = Mutex.new
45 # semaphore.synchronize {
46 # # access shared resource
51 # semaphore.synchronize {
52 # # access shared resource
63 @waiting.taint # enable tainted comunication
68 # Returns +true+ if this lock is currently held by some thread.
75 # Attempts to obtain the lock and returns immediately. Returns +true+ if the
80 Thread.critical = true
85 Thread.critical = false
90 # Attempts to grab the lock and waits if it isn't available.
93 while (Thread.critical = true; @locked)
94 @waiting.push Thread.current
98 Thread.critical = false
103 # Releases the lock. Returns +nil+ if ref wasn't locked.
106 return unless @locked
107 Thread.critical = true
115 Thread.critical = false
124 # Obtains a lock, runs the block, and releases the lock when the block
125 # completes. See the example under Mutex.
137 # If the mutex is locked, unlocks the mutex, wakes one waiting thread, and
138 # yields in a critical section.
141 return unless @locked
157 # ConditionVariable objects augment class Mutex. Using condition variables,
158 # it is possible to suspend while in the middle of a critical section until a
159 # resource becomes available.
166 # resource = ConditionVariable.new
169 # mutex.synchronize {
170 # # Thread 'a' now needs the resource
171 # resource.wait(mutex)
172 # # 'a' can now have the resource
177 # mutex.synchronize {
178 # # Thread 'b' has finished using the resource
183 class ConditionVariable
185 # Creates a new ConditionVariable
192 # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
196 mutex.exclusive_unlock do
197 @waiters.push(Thread.current)
206 # Wakes up the first thread in line waiting for this lock.
218 # Wakes up all threads waiting for this lock.
223 waiters0 = @waiters.dup
236 # This class provides a way to synchronize communication between threads.
244 # producer = Thread.new do
246 # sleep rand(i) # simulate expense
248 # puts "#{i} produced"
252 # consumer = Thread.new do
255 # sleep rand(i/2) # simulate expense
256 # puts "consumed #{value}"
264 # Creates a new queue.
269 @que.taint # enable tainted comunication
275 # Pushes +obj+ to the queue.
278 Thread.critical = true
286 Thread.critical = false
305 # Retrieves data from the queue. If the queue is empty, the calling thread is
306 # suspended until data is pushed onto the queue. If +non_block+ is true, the
307 # thread isn't suspended, and an exception is raised.
309 def pop(non_block=false)
310 while (Thread.critical = true; @que.empty?)
311 raise ThreadError, "queue empty" if non_block
312 @waiting.push Thread.current
317 Thread.critical = false
331 # Returns +true+ is the queue is empty.
338 # Removes all objects from the queue.
345 # Returns the length of the queue.
357 # Returns the number of threads waiting on the queue.
365 # This class represents queues of specified size capacity. The push operation
366 # may be blocked if the capacity is full.
368 # See Queue for an example of how a SizedQueue works.
370 class SizedQueue<Queue
372 # Creates a fixed-length queue with a maximum size of +max+.
375 raise ArgumentError, "queue size must be positive" unless max > 0
378 @queue_wait.taint # enable tainted comunication
383 # Returns the maximum size of the queue.
390 # Sets the maximum size of the queue.
393 Thread.critical = true
396 Thread.critical = false
400 Thread.critical = false
403 t = @queue_wait.shift
414 # Pushes +obj+ to the queue. If there is no space left in the queue, waits
415 # until space becomes available.
418 Thread.critical = true
419 while @que.length >= @max
420 @queue_wait.push Thread.current
422 Thread.critical = true
438 # Retrieves data from the queue and runs a waiting thread, if any.
442 Thread.critical = true
443 if @que.length < @max
445 t = @queue_wait.shift
450 Thread.critical = false
471 # Returns the number of threads waiting on the queue.
474 @waiting.size + @queue_wait.size
478 # Documentation comments:
479 # - How do you make RDoc inherit documentation from superclass?