diff options
author | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-16 18:49:26 +0900 |
---|---|---|
committer | Jari Vetoniemi <jari.vetoniemi@indooratlas.com> | 2020-03-30 00:39:06 +0900 |
commit | fcbf63e62c627deae76c1b8cb8c0876c536ed811 (patch) | |
tree | 64cb17de3f41a2b6fef2368028fbd00349946994 /jni/ruby/lib/thwait.rb |
Fresh start
Diffstat (limited to 'jni/ruby/lib/thwait.rb')
-rw-r--r-- | jni/ruby/lib/thwait.rb | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/jni/ruby/lib/thwait.rb b/jni/ruby/lib/thwait.rb new file mode 100644 index 0000000..d9750a4 --- /dev/null +++ b/jni/ruby/lib/thwait.rb @@ -0,0 +1,140 @@ +# +# thwait.rb - thread synchronization class +# $Release Version: 0.9 $ +# $Revision: 1.3 $ +# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd.) + +require "thread.rb" +require "e2mmap.rb" + +# +# 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 +# +# +# th = ThreadsWait.new(thread1,...) +# th.next_wait # next one to be done +# +# +class ThreadsWait + extend Exception2MessageMapper + def_exception("ErrNoWaitingThread", "No threads for waiting.") + def_exception("ErrNoFinishedThread", "No finished threads.") + + # + # Waits until all specified threads have terminated. If a block is provided, + # it is executed for each thread as they terminate. + # + 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 that have not terminated yet. + attr_reader :threads + + # + # Returns +true+ if there are no threads in the pool still running. + # + def empty? + @threads.empty? + end + + # + # Returns +true+ if any thread has terminated and is ready to be collected. + # + def finished? + !@wait_queue.empty? + end + + # + # Waits for specified threads to terminate, and returns when one of + # the threads terminated. + # + 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 + for th in threads + 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 is no thread to wait, raises +ErrNoWaitingThread+. If +nonblock+ + # is true, and there is no terminated thread, raises +ErrNoFinishedThread+. + # + 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 + + # + # 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 + +## +# An alias for ThreadsWait from thwait.rb + +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. |