Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

176 lines (157 sloc) 4.429 kb
#
# thwait.rb - thread synchronization class
# $Release Version: 0.9 $
# $Revision: 1.3 $
# $Date: 1998/06/26 03:19:34 $
# by Keiju ISHITSUKA(Nihpon Rational Software Co.,Ltd.)
# modernized by Evan Phoenix - 2011
# --
# feature:
# provides synchronization for multiple threads.
#
# class methods:
# * ThreadsWait.all_waits(thread1,...)
# waits until all of specified threads are terminated.
# if a block is supplied for the method, evaluates it for
# each thread termination.
# * th = ThreadsWait.new(thread1,...)
# creates synchronization object, specifying thread(s) to wait.
#
# methods:
# * th.threads
# list threads to be synchronized
# * th.empty?
# is there any thread to be synchronized.
# * th.finished?
# is there already terminated thread.
# * th.join(thread1,...)
# wait for specified thread(s).
# * th.join_nowait(threa1,...)
# specifies thread(s) to wait. non-blocking.
# * th.next_wait
# waits until any of specified threads is terminated.
# * th.all_waits
# waits until all of specified threads are terminated.
# if a block is supplied for the method, evaluates it for
# each thread termination.
#
require "thread"
#
# This class watches for termination of multiple threads. Basic functionality
# (wait until specified threads have terminated) can be accessed through the
# class method ThreadsWait::all_waits. Finer control can be gained using
# instance methods.
#
# Example:
#
# ThreadsWait.all_waits(thr1, thr2, ...) do |t|
# STDERR.puts "Thread #{t} has terminated."
# end
#
class ThreadsWait
RCS_ID='-$Id: thwait.rb:git 1.4 2011/01/24 00:00:00 evan $-'
class ErrNoWaitingThread < StandardError
end
class ErrNoFinishedThread < StandardError
end
#
# Waits until all specified threads have terminated. If a block is provided,
# it is executed for each thread termination.
#
def ThreadsWait.all_waits(*threads) # :yield: thread
tw = ThreadsWait.new(*threads)
if block_given?
tw.all_waits do |th|
yield th
end
else
tw.all_waits
end
end
#
# Creates a ThreadsWait object, specifying the threads to wait on.
# Non-blocking.
#
def initialize(*threads)
@threads = []
@wait_queue = Queue.new
join_nowait(*threads) unless threads.empty?
end
# Returns the array of threads in the wait queue.
attr_reader :threads
#
# Returns +true+ if there are no threads to be synchronized.
#
def empty?
@threads.empty?
end
#
# Returns +true+ if any thread has terminated.
#
def finished?
!@wait_queue.empty?
end
#
# Waits for specified threads to terminate.
#
def join(*threads)
join_nowait(*threads)
next_wait
end
#
# Specifies the threads that this object will wait for, but does not actually
# wait.
#
def join_nowait(*threads)
threads.flatten!
@threads.concat threads
threads.each do |th|
Thread.start(th) do |t|
begin
t.join
ensure
@wait_queue.push t
end
end
end
end
#
# Waits until any of the specified threads has terminated, and returns the one
# that does.
#
# If there are no pending threads to wait for, raises +ErrNoWaitingThread+.
# If +nonblock+ is true and there is no terminated thread,
# raises +ErrNoFinishedThread+.
#
def next_wait(nonblock=nil)
raise ErrNoWaitingThread, "No threads for waiting" if @threads.empty?
begin
th = @wait_queue.pop(nonblock)
@threads.delete th
return th
rescue ThreadError
raise ErrNoFinishedThread, "No finished threads"
end
end
#
# Waits until all of the specified threads are terminated. If a block is
# supplied for the method, it is executed for each thread termination.
#
# Raises exceptions in the same manner as +next_wait+.
#
def all_waits
until @threads.empty?
th = next_wait
yield th if block_given?
end
end
end
# deprecated alias
ThWait = ThreadsWait
# Documentation comments:
# - Source of documentation is evenly split between Nutshell, existing
# comments, and my own rephrasing.
# - I'm not particularly confident that the comments are all exactly correct.
# - The history, etc., up the top appears in the RDoc output. Perhaps it would
# be better to direct that not to appear, and put something else there
# instead.
Jump to Line
Something went wrong with that request. Please try again.