1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Added RDoc comments. Several TODOs remain; see comments at EOF.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3352 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
gsinclair 2003-01-17 09:30:11 +00:00
parent b63bab709a
commit 94d28746c2

View file

@ -21,6 +21,9 @@ if $DEBUG
Thread.abort_on_exception = true
end
#
# FIXME: not documented in Pickaxe or Nutshell.
#
def Thread.exclusive
_old = Thread.critical
begin
@ -31,6 +34,27 @@ def Thread.exclusive
end
end
#
# +Mutex+ implements a simple semaphore that can be used to coordinate access to
# shared data from multiple concurrent threads.
#
# Example:
#
# require 'thread'
# semaphore = Mutex.new
#
# a = Thread.new {
# semaphore.synchronize {
# # access shared resource
# }
# }
#
# b = Thread.new {
# semaphore.synchronize {
# # access shared resource
# }
# }
#
class Mutex
def initialize
@waiting = []
@ -39,10 +63,17 @@ class Mutex
self.taint
end
#
# Returns +true+ if this lock is currently held by some thread.
#
def locked?
@locked
end
#
# Attempts to obtain the lock and returns immediately. Returns +true+ if the
# lock was granted.
#
def try_lock
result = false
Thread.critical = true
@ -54,6 +85,9 @@ class Mutex
result
end
#
# Attempts to grab the lock and waits if it isn't available.
#
def lock
while (Thread.critical = true; @locked)
@waiting.push Thread.current
@ -64,6 +98,9 @@ class Mutex
self
end
#
# Releases the lock. Returns +nil+ if ref wasn't locked.
#
def unlock
return unless @locked
Thread.critical = true
@ -82,6 +119,10 @@ class Mutex
self
end
#
# Obtains a lock, runs the block, and releases the lock when the block
# completes. See the example under +Mutex+.
#
def synchronize
lock
begin
@ -91,6 +132,9 @@ class Mutex
end
end
#
# FIXME: not documented in Pickaxe/Nutshell.
#
def exclusive_unlock
return unless @locked
Thread.exclusive do
@ -107,11 +151,41 @@ class Mutex
end
end
#
# +ConditionVariable+ objects augment class +Mutex+. Using condition variables,
# it is possible to suspend while in the middle of a critical section until a
# resource becomes available (see the discussion on page 117).
#
# Example:
#
# require 'thread'
#
# mutex = Mutex.new
# resource = ConditionVariable.new
#
# a = Thread.new {
# mutex.synchronize {
# # Thread 'a' now needs the resource
# resource.wait(mutex)
# # 'a' can now have the resource
# }
# }
#
# b = Thread.new {
# mutex.synchronize {
# # Thread 'b' has finished using the resource
# resource.signal
# }
# }
#
class ConditionVariable
def initialize
@waiters = []
end
#
# Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup.
#
def wait(mutex)
mutex.exclusive_unlock do
@waiters.push(Thread.current)
@ -120,6 +194,9 @@ class ConditionVariable
mutex.lock
end
#
# Wakes up the first thread in line waiting for this lock.
#
def signal
begin
t = @waiters.shift
@ -129,6 +206,9 @@ class ConditionVariable
end
end
#
# Wakes up all threads waiting for this lock.
#
def broadcast
waiters0 = nil
Thread.exclusive do
@ -144,7 +224,16 @@ class ConditionVariable
end
end
#
# This class provides a way to communicate data between threads.
#
# TODO: an example (code or English) would really help here. How do you set up
# a queue between two threads?
#
class Queue
#
# Creates a new queue.
#
def initialize
@que = []
@waiting = []
@ -153,6 +242,9 @@ class Queue
self.taint
end
#
# Pushes +obj+ to the queue.
#
def push(obj)
Thread.critical = true
@que.push obj
@ -172,6 +264,11 @@ class Queue
alias << push
alias enq push
#
# Retrieves data from the queue. If the queue is empty, the calling thread is
# suspended until data is pushed onto the queue. If +non_block+ is true, the
# thread isn't suspended, and an exception is raised.
#
def pop(non_block=false)
while (Thread.critical = true; @que.empty?)
raise ThreadError, "queue empty" if non_block
@ -185,27 +282,50 @@ class Queue
alias shift pop
alias deq pop
#
# Returns +true+ is the queue is empty.
#
def empty?
@que.empty?
end
#
# Removes all objects from the queue.
#
def clear
@que.clear
end
#
# Returns the length of the queue.
#
def length
@que.length
end
#
# Alias of length.
#
def size
length
end
#
# Returns the number of threads waiting on the queue.
#
def num_waiting
@waiting.size
end
end
#
# This class represents queues of specified size capacity. The +push+ operation
# may be blocked if the capacity is full.
#
class SizedQueue<Queue
#
# Creates a fixed-length queue with a maximum size of +max+.
#
def initialize(max)
raise ArgumentError, "queue size must be positive" unless max > 0
@max = max
@ -214,10 +334,16 @@ class SizedQueue<Queue
super()
end
#
# Returns the maximum size of the queue.
#
def max
@max
end
#
# Sets the maximum size of the queue.
#
def max=(max)
Thread.critical = true
if max <= @max
@ -277,3 +403,13 @@ class SizedQueue<Queue
@waiting.size + @queue_wait.size
end
end
# Documentation comments:
# - SizedQueue #push and #pop deserve some documentation, as they are different
# from the Queue implementations.
# - Some methods are not documented in Pickaxe/Nutshell, and are therefore not
# documented here. See FIXME notes.
# - Reference to Pickaxe page numbers should be replaced with either a section
# name or a summary.
# - How do you document aliases?
# - How do you make RDoc inherit documentation from superclass?