Class Completed


  • public class Completed
    extends java.lang.Object
    A helper-class that performs Thread-managment for the class Torello.Java.OSResponse

    Helper Class for Torello.Java.OSResponse

    This class primarily functions as a support role to OSResponse (which in turn is a data-output class for: Shell, Shell.XL and the GCP Shell Class GSUTIL ).

    If the methods in this class do not appear to be 'generally applicable utilities' that is because they are specifically tailored to reading Process-Output (Standard-Out & Standard-Error) from Operating System calls.

    The four helpers for OSResponse are: AppendableTap, Completed, ISPT and NOPRINT

    This class helps a Thread wait for the situation where all Thread's that have 'registered' with this class have reported 'finished' messages. This class offers two wait methods that will halt progress on the current Thread until all registered Thread's have reported a 'finished' message.

    It is important to note, that the reporting of an exception is not sufficient messaging for informing an instance of 'Completed' that a Thread has run to completion. Rather, if the invoking thread has the ability to tell this class that exceptions have occurred, it should also have the ability to report when it consider Thread progress to have run to termination. This means that if writing a try-catch block, inside the catch an invocation of Completed.exceptionWasThrown should be followed by a finally block that relays that the method or thread has completed it's work.

    When an instance of this class 'Completed' has been told to wait, the invoking Thread will not proceed until all the registered Thread's have reported a 'finished' message (by using the 'finished' method).


    • Constructor Summary

      Constructors 
      Constructor Description
      Completed()
      A simple, zero-argument, constructor.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void addThread​(Thread thread)
      Registers another Thread with this monitor.
      void clear()
      Fully resets the internal state of this instance of Completed.
      boolean exceptionWasThrown​(Thread thread, Exception exception)
      This method may be invoked to tell this instance of Completed that a particular Thread has thrown an Exception.
      protected void finalize()
      Makes sure the Thread's are cleared out of the internal-storage Vector's
      protected int find​(Thread thread)
      Provided a given input Thread parameter, this method retrieves the Vector-index location inside the internal-storage Vector's for that Thread.
      void finished​(Thread thread)
      Informs this 'Completed' class instance that the 'thread' instance has run to completion.
      void ifExceptionThrowException()
      This method throws a wrapper-Exception (CompletionException) that wraps any Exceptions which were thrown by the other Thread's which have added themselves to this class - and have reported those exceptions to this instance
      static String nameAndId​(Thread thread)
      Converts a Thread to a String using it's name and id fields.
      void reset()
      This takes 'this' instance of 'Completed' and removes any registered exceptions that have been reported to 'this' instance, from the internal storage Vector's.
      void waitForCompletionOf​(Thread... threads)
      This method will run until the specified threads have finished their assignments.
      void waitForCompletionOfAllThreads()
      This method will run until all Thread's have finished their assignments.
      • Methods inherited from class java.lang.Object

        clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

    • Method Detail

      • finalize

        🡅  🡇    
        protected void finalize()
        Makes sure the Thread's are cleared out of the internal-storage Vector's
        Overrides:
        finalize in class java.lang.Object
        Code:
        Exact Method Body:
         watchedThreads.clear(); watchedThreads  = null;
         exceptions.clear();     exceptions      = null;
         finished.clear();       finished        = null;
        
      • find

        🡅  🡇    
        protected int find​(java.lang.Thread thread)
        Provided a given input Thread parameter, this method retrieves the Vector-index location inside the internal-storage Vector's for that Thread.
        Parameters:
        thread - This may be any Java Thread instance, but only ones which were registered previously with this Completed instance can be found in the internal-storage.
        Returns:
        Returns the index / location within the internal-storage Vector's of the provided Thread.
        Code:
        Exact Method Body:
         for (int i=0; i < watchedThreads.size(); i++)
             if (thread == watchedThreads.elementAt(i))
                 return i;
        
         return -1;
        
      • clear

        🡅  🡇    
        public void clear()
        Fully resets the internal state of this instance of Completed. Afterwards, the behavior of 'this' instance should be identical to one where 'this' had just been created by the constructor.
        Code:
        Exact Method Body:
         watchedThreads.clear();
         exceptions.clear();
         finished.clear();
        
         waitHasBeenCalled = false;
        
      • reset

        🡅  🡇    
        public void reset()
        This takes 'this' instance of 'Completed' and removes any registered exceptions that have been reported to 'this' instance, from the internal storage Vector's. It also removes any / all responses that this instance has received from the registered Thread's.

        NOTE: Unlike method clear(), this method does not remove the registered Thread's, themselves!.
        Code:
        Exact Method Body:
         for (int i=0; i < exceptions.size(); i++) exceptions.setElementAt(null, i);
        
         for (int i=0; i < finished.size(); i++) finished.setElementAt(Boolean.FALSE, i);
        
      • nameAndId

        🡅  🡇    
        public static java.lang.String nameAndId​(java.lang.Thread thread)
        Converts a java.lang.Thread to a String using it's name and id fields.
        Parameters:
        thread - This may be any java Thread.
        Returns:
        a Java String that contains the values in Thread.getID() and also Thread.getName(). If Thread.getName() returns null, then the name printed will simply be "Name Not Available"
        Code:
        Exact Method Body:
         return "Thread [ID: " + thread.getId() + ", Name: " +
             ((thread.getName() != null) ? thread.getName() : "Name Not Available") + "]";
        
      • addThread

        🡅  🡇    
        public void addThread​(java.lang.Thread thread)
        Registers another Thread with this monitor.

        NOTE: Once a Thread has been registered, this class will accept 'finished' and 'exceptionWasThrown' messages (invocations) from that Thread - once a waitForCompletionOf... has been called.
        Parameters:
        thread - This may be any Java Thread. This thread will be registered with this class. Registering allows Thread's to send 'finished' messages to this monitor class (by-way-of calling this class Completed.finished method.
        Throws:
        java.lang.IllegalArgumentException - If the 'thread' parameter instance has already been registered with this instance of 'Completed' (using this addThread(Thread) method, then IllegalArgumentException will throw.
        java.lang.IllegalThreadStateException - If an attempt is made to add a Thread to this instance of Completed (using this method, Completed.addThread), *after* a call to one of the Completed.waitForCompletion... methods have been invoked. Once a call to a wait method has been made, new Thread's to monitor cannot be added using this method until all previously added thread's have sent 'finished' messages, and a call to either clear() or reset() has been made.
        Code:
        Exact Method Body:
         if (find(thread) != -1) throw new IllegalArgumentException(
             "This " + nameAndId(thread) + " has already been added to this instance of " +
             "class 'Completed'."
         );
        
         if (waitHasBeenCalled) throw new IllegalThreadStateException(
             "This instance of Completed has already been issued a waitForCompletion... method " +
             "invocation, and is not currently accepting new Thread's to add to it's internal " +
             "list of threads to wait on.  In order for class Completed to wait for a thread to " +
             "finish, that thread must be registered with this instance (using this method " +
             "'addThread') *BEFORE* a call to waitForCompletion is made."
         );
        
         watchedThreads.add(thread);
         exceptions.add(null);
         finished.add(Boolean.FALSE);
        
      • exceptionWasThrown

        🡅  🡇    
        public boolean exceptionWasThrown​(java.lang.Thread thread,
                                          java.lang.Exception exception)
        This method may be invoked to tell this instance of Completed that a particular Thread has thrown an Exception. The thrown 'exception' will be recorded, and may even be retrieved later (or thrown), if needed.

        Internally, the Exception will be stored and associated with the 'thread' parameter.

        IMPORTANT: Even after an 'exception throw' message is sent to an instance of this class (using this method, 'Completed.exceptionWasThrown'), Completed will still wait for the Thread that registered this exception to finish. Regardless of reported-exceptions, it is always necessary to send 'finished' messages to this class (using method 'Completed.finished') for each Thread that this instance is waiting on.
        Parameters:
        thread - This is the Thread that has thrown the 'exception'
        exception - This is the Exception that was thrown.
        Returns:
        This method will return TRUE, unless the 'thread' parameter has already had an exception reported about it. It is neither mandatory nor critical to heed this return-value. It just reports whether this is the first 'Exception' reported about the 'thread' parameter.
        Throws:
        java.lang.IllegalStateException - This exception throws if this instance of 'Completed' has not received a call to one of the waitForCompletion... methods already. Reporting that one of the Thread's on which this class is "waiting for Completion" has thrown an exception, without first telling this instance to wait will cause IllegalStateException.
        java.lang.IllegalArgumentException - This exception throws if the 'thread' parameter was not actually registered with this instance of 'Completed'. In order for an instance of Completed to heed either 'finished' or 'exception' messages from a Thread, that Thread must first have been registered with the instance using the addThread(Thread) method.
        See Also:
        addThread(Thread), find(Thread)
        Code:
        Exact Method Body:
         if (! waitHasBeenCalled) throw new IllegalStateException(
             "An 'exception-throw' message has been sent to this instance of Completed by " +
             nameAndId(thread) + ", but unfortunately, no invocations of 'wait' have been issued " +
             "to this class yet.  Exception-throw messages (which are explicitly sent by calling " +
             "this method, 'exceptionWasThrown') CANNOT be sent until one of the " +
             "'waitForCompletion...' methods have been invoked."
         );
        
         int pos = find(thread);
        
         if (pos == -1) throw new IllegalArgumentException(
             "The " + nameAndId(thread) + ", for which this this method 'exceptionWasThrown' " +
             "was invoked has not been registered with this instance of 'Completed' (using the " +
             "Completed.addThread(...) method prior to the calling 'exceptionWasThrown'."
         );
        
         boolean ret = exceptions.elementAt(pos) == null;
        
         exceptions.setElementAt(exception, pos);
        
         return ret;
        
      • finished

        🡅  🡇    
        public void finished​(java.lang.Thread thread)
        Informs this 'Completed' class instance that the 'thread' instance has run to completion. Attempts to wake up the monitor Thread running this instance of Completed using this.notify() to check if all Thread's that are being monitored have completed
        Parameters:
        thread - This is the Thread that has completed it's task.
        Throws:
        java.lang.IllegalStateException - This exception throws if this instance of 'Completed' has not received a call to one of the waitForCompletion... methods already. Reporting that one of the Thread's on which this class is "waiting for Completion" has finished, without first telling this instance to wait will cause IllegalStateException.
        java.lang.IllegalArgumentException - This exception throws if the 'thread' parameter was not actually registered with this instance of 'Completed'. In order for an instance of Completed to heed either 'finished' or 'exception' messages from a Thread, that Thread must first have been registered with the instance using the Completed.addThread(Thread) method.
        java.lang.IllegalThreadStateException - If a second finished message is sent for a particular registered-Thread (as in registered earlier through the addThread method) then this exception will throw. Unless calls to either reset() or clear() are made, multiple invocations of 'finished' cannot be made using the exact same Thread parameter.
        See Also:
        addThread(Thread), find(Thread)
        Code:
        Exact Method Body:
         if (! waitHasBeenCalled) throw new IllegalStateException(
             "A 'finished' message has been sent to this instance of Completed by " +
             nameAndId(thread) + ", but unfortunately, no invocations of 'wait' have been issued " +
             "to this class yet.  Finished messages (which are explicitly sent by calling this " +
             "method, 'finished') CANNOT be sent until one of the 'waitForCompletion...' methods " +
             "have been invoked."
         );
        
         int pos = find(thread);
        
         if (pos == -1) throw new IllegalArgumentException(
             "The " + nameAndId(thread) + " for which this this method 'finished' was invoked " +
             "was not not registered using this class 'addThread' method prior to calling " + 
             "'finished'"
         );
        
         if (finished.elementAt(pos) == Boolean.TRUE) throw new IllegalThreadStateException(
             "A 'finished' message has already been sent by " + nameAndId(thread) + " to this " +
             "instance of Complete.  This instance must be issued a 'clear' or 'reset' " +
             "message (by calling methods with these names) first before reporting that this " +
             "Thread has finished again."
         );
        
         finished.setElementAt(Boolean.TRUE, pos);
        
         // THE NOTIFY IS DONE HERE
         this.notify();
        
      • waitForCompletionOfAllThreads

        🡅  🡇    
        public void waitForCompletionOfAllThreads()
                                           throws java.lang.InterruptedException
        This method will run until all Thread's have finished their assignments.

        This method shall:

        1. First, this method checks whether all registered Thread's (which must have been registered using the addThread(Thread) method) have already reported 'finished' messages using the method finished(Thread). If all registered Thread's have finished, this method shall exit gracefully.

        2. Next, if there are registered Thread's that have not completed, then this method shall make a call to this.wait(), and halt the current Thread's progress until 'this' instance receives a notify() call from the JVM's Object.notify() mechanism. It is important to note that when any other method calls this class' 'finished(Thread)' method, the code in this class will call this.notify() and wake up any other dormant or 'sleeping' Thread's. When all Thread's have reported 'finished(Thread)' then and only then shall this method shall exit. If there are other threads that need to complete, then this method will invoke this.wait() until they have.
        Throws:
        java.lang.IllegalStateException - If this method is invoked, but no Thread's have been registered with this instance of 'Completed' (using the Completed.addThread method), then this exception will throw. This is because there would be nothing for this method to do, as in this case there would be no registered Thread's to wait on.
        java.lang.IllegalThreadStateException - If this instance of completed has already been asked to 'wait' for thread completion, then this exception shall throw. A 'wait' message should only be invoked on an instance of Completed once.

        Note that both the reset() and the clear() methods shall reset this instance's flags - regardless of whether a 'wait' request has already been issued.
        If - the JVM internal process is interrupted by some other Thread then an InterruptedException will throw.
        java.lang.InterruptedException
        Code:
        Exact Method Body:
         if (watchedThreads.size() == 0) throw new IllegalStateException(
             "This instance of Complete has not received any calls to its 'addThread' method, " +
             "and therefore does not have any Thread's to wait on for completion."
         );
        
         if (waitHasBeenCalled) throw new IllegalThreadStateException(
             "A 'wait' method has already been invoked on this class.  'reset' or 'clear' must " +
             "be invoked, or a new instance of Completed must be created before calling any " +
             "more 'waitForCompletion...' methods."
         );
        
         waitHasBeenCalled = true;
        
         for (Thread thread : watchedThreads) thread.start();
        
         while (true)
         {
             boolean allThreadsHaveFinished = true;
        
             HERE:
             for (Boolean threadIsFinished : finished)
        
                 if (! threadIsFinished.booleanValue())
                 {
                     allThreadsHaveFinished = false;
                     break HERE;
                 }
        
             if (allThreadsHaveFinished) return; // All Tasks have finished!
        
             else this.wait();   // Let another Thread start up!
                                 // There are more tasks that aren't done!
         }
        
      • waitForCompletionOf

        🡅  🡇    
        public void waitForCompletionOf​(java.lang.Thread... threads)
                                 throws java.lang.InterruptedException
        This method will run until the specified threads have finished their assignments.

        This method shall:

        1. First, this method checks whether the Thread's which are listed by parameter 'threads' (each of which must have registered using the addThread(Thread) method) have already reported 'finished' messages using the method finished(Thread). If every Thread listed by Varargs parameter 'threads' has finished, then this method shall simply exit gracefully.

        2. Next, if some of the Thread's listed in parameter 'threads' have not completed, then this method shall make a call to this.wait(), and halt the current Thread's progress until 'this' instance receives a notify() call from the JVM's Object.notify() mechanism. It is important to note that when any other method calls this class' 'finished(Thread)' method, the code in this class will call this.notify() and wake up any other dormant or 'sleeping' Thread's that are using 'this' object as a waiting-lock. When all Thread's listed as input have reported 'finished(Thread)' - then and and only then shall this method exit. When 'this' instance receives a JVM notify() message, if there are other Thread's that still need to complete, then this method shall invoke this.wait() again (until all listed Thread's have completed).
        Parameters:
        threads - This Varargs parameter shall take a list of Thread's for this instance of Completed to check-on and wait-for completion. It is important to note that the Thread's in this parameter must have been registered with this class (using the addThread(Thread) method, or else an IllegalArgumentException shall throw.
        Throws:
        java.lang.IllegalStateException - If this method is invoked, but no Thread's have been registered with this instance of 'Completed' (using the Completed.addThread method), then this exception will throw. This is because there would be nothing for this method to do, as in this case there would be no registered Thread's to wait on.
        java.lang.IllegalThreadStateException - If this instance of completed has already been asked to 'wait' for thread completion, then this exception shall throw. A 'wait' message should only be invoked on an instance of Completed once.

        Note that both the reset() and the clear() methods shall reset this instance's flags - regardless of whether a 'wait' request has already been issued.
        java.lang.IllegalArgumentException - If any of the Thread's listed in 'threads' Var-Args Parameter were not added to this class using the addThread(Thread) method, then an IllegalArgumentException will throw.
        java.lang.NullPointerException - if any of the 'threads' passed to the Varargs parameter are null references.
        If - the JVM internal process is interrupted by some other Thread then an InterruptedException will throw.
        java.lang.InterruptedException
        Code:
        Exact Method Body:
         if (watchedThreads.size() == 0) throw new IllegalStateException(
             "This instance of Complete has not received any calls to its 'addThread' method, " +
             "and therefore does not have any Thread's to wait on for completion."
         );
        
         if (waitHasBeenCalled) throw new IllegalThreadStateException(
             "A 'wait' method has already been invoked on this class.  'reset' must be " +
             "invoked, or a new instance of Completed must be created"
         );
        
         int[] posArr = new int[threads.length];
        
         for (int i=0; i < threads.length; i++)
         {
             if (threads[i] == null) throw new NullPointerException(
                 "The " + i + StringParse.ordinalIndicator(i) + " element of the input Thread-" +
                 "Array was null"
             );
        
             posArr[i] = find(threads[i]);
        
             if (posArr[i] == -1) throw new IllegalArgumentException(
                 "One of the threads passed to this method was never registered using the " +
                 "'addThread' method."
             );
         }
        
         waitHasBeenCalled = true;
        
         for (int threadIndex : posArr) watchedThreads.elementAt(threadIndex).start();
        
         while (true)
         {
             boolean allThreadsHaveFinished = true;
        
             HERE:
             for (int pos : posArr)
        
                 if (! finished.elementAt(pos).booleanValue()) 
                 {
                     allThreadsHaveFinished = false;
                     break HERE;
                 }
        
             if (allThreadsHaveFinished) return; // All Tasks have finished!
        
             else this.wait();   // Let another Thread start up!
                                 // There are more tasks that aren't done!
         }
        
      • ifExceptionThrowException

        🡅    
        public void ifExceptionThrowException()
        This method throws a wrapper-Exception (CompletionException) that wraps any Exceptions which were thrown by the other Thread's which have added themselves to this class - and have reported those exceptions to this instance
        Throws:
        java.util.concurrent.CompletionException - An 'unchecked' Exception (inherits from class java.lang.RuntimeException) which wraps any exception which has been thrown and reported to 'this' instance, by the Thread's registered to this instance.
        Code:
        Exact Method Body:
         int pos=0;
        
         while (pos < exceptions.size())
        
             if (exceptions.elementAt(pos) != null) break;
             else pos++;
        
         if (pos == exceptions.size()) return;
        
         Thread thread      = watchedThreads.elementAt(pos);
         String name        = thread.getName();
         String description = "Thread ID: [" + thread.getId() + "]";
        
         if (name != null) description += ", Thread Name: [" + name + "]";
        
         for (Exception e : exceptions) if (e != null) throw new CompletionException(
             "There was an exception when attempting to execute this command.  Please see this " +
             "exception's 'Throwable.getCause()' method for more details." + description, e
         );