123456789_123456789_123456789_123456789_123456789_

Class: ThreadsWait

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Exception2MessageMapper
Inherits: Object
Defined in: lib/thwait.rb

Overview

This class watches for termination of multiple threads. Basic functionality (wait until specified threads have terminated) can be accessed through the class method .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

th = ThreadsWait.new(thread1,...)
th.next_wait # next one to be done

Class Method Summary

Instance Attribute Summary

  • #empty? ⇒ Boolean readonly

    Returns true if there are no threads in the pool still running.

  • #finished? ⇒ Boolean readonly

    Returns true if any thread has terminated and is ready to be collected.

  • #threads readonly

    Returns the array of threads that have not terminated yet.

Instance Method Summary

  • #all_waits

    Waits until all of the specified threads are terminated.

  • #join(*threads)

    Waits for specified threads to terminate, and returns when one of the threads terminated.

  • #join_nowait(*threads)

    Specifies the threads that this object will wait for, but does not actually wait.

  • #next_wait(nonblock = nil)

    Waits until any of the specified threads has terminated, and returns the one that does.

Constructor Details

.new(*threads) ⇒ ThreadsWait

Creates a ThreadsWait object, specifying the threads to wait on. Non-blocking.

[ GitHub ]

  
# File 'lib/thwait.rb', line 51

def initialize(*threads)
  @threads = []
  @wait_queue = Thread::Queue.new
  join_nowait(*threads) unless threads.empty?
end

Class Method Details

.all_waits(*threads)

Waits until all specified threads have terminated. If a block is provided, it is executed for each thread as they terminate.

[ GitHub ]

  
# File 'lib/thwait.rb', line 36

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

Instance Attribute Details

#empty?Boolean (readonly)

Returns true if there are no threads in the pool still running.

[ GitHub ]

  
# File 'lib/thwait.rb', line 63

def empty?
  @threads.empty?
end

#finished?Boolean (readonly)

Returns true if any thread has terminated and is ready to be collected.

[ GitHub ]

  
# File 'lib/thwait.rb', line 70

def finished?
  !@wait_queue.empty?
end

#threads (readonly)

Returns the array of threads that have not terminated yet.

[ GitHub ]

  
# File 'lib/thwait.rb', line 58

attr_reader :threads

Instance Method Details

#all_waits

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.

[ GitHub ]

  
# File 'lib/thwait.rb', line 124

def all_waits
  until @threads.empty?
    th = next_wait
    yield th if block_given?
  end
end

#join(*threads)

Waits for specified threads to terminate, and returns when one of the threads terminated.

[ GitHub ]

  
# File 'lib/thwait.rb', line 78

def join(*threads)
  join_nowait(*threads)
  next_wait
end

#join_nowait(*threads)

Specifies the threads that this object will wait for, but does not actually wait.

[ GitHub ]

  
# File 'lib/thwait.rb', line 87

def join_nowait(*threads)
  threads.flatten!
  @threads.concat threads
  for th in threads
    Thread.start(th) do |t|
      begin
        t.join
      ensure
        @wait_queue.push t
      end
    end
  end
end

#next_wait(nonblock = nil)

Waits until any of the specified threads has terminated, and returns the one that does.

If there is no thread to wait, raises ErrNoWaitingThread. If nonblock is true, and there is no terminated thread, raises ErrNoFinishedThread.

[ GitHub ]

  
# File 'lib/thwait.rb', line 108

def next_wait(nonblock = nil)
  ThreadsWait.fail ErrNoWaitingThread if @threads.empty?
  begin
    @threads.delete(th = @wait_queue.pop(nonblock))
    th
  rescue ThreadError
    ThreadsWait.fail ErrNoFinishedThread
  end
end