From 8e42258541d7d04699d80ae90b73896cd82fd360 Mon Sep 17 00:00:00 2001
From: brinn <brinn>
Date: Sat, 17 Dec 2011 19:52:13 +0000
Subject: [PATCH] Support named callables.

SVN: 24031
---
 .../common/concurrent/TerminableCallable.java | 108 +++++++++++-------
 1 file changed, 64 insertions(+), 44 deletions(-)

diff --git a/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java b/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java
index 99da37521c5..041c1bbb8b6 100644
--- a/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java
+++ b/common/source/java/ch/systemsx/cisd/common/concurrent/TerminableCallable.java
@@ -21,6 +21,8 @@ import java.util.concurrent.Callable;
 import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
 import ch.systemsx.cisd.base.exceptions.InterruptedExceptionUnchecked;
 import ch.systemsx.cisd.base.exceptions.StopException;
+import ch.systemsx.cisd.base.namedthread.ICallableNameProvider;
+import ch.systemsx.cisd.base.namedthread.NamedRunnable;
 import ch.systemsx.cisd.common.utilities.ITerminable;
 
 /**
@@ -35,16 +37,16 @@ import ch.systemsx.cisd.common.utilities.ITerminable;
  * {@link Thread#interrupt()} and <code>Thread.stop()</code>) should be executed in the
  * <var>stoppableExecutor</var>.
  * <p>
- * <strong>Note: Code executed in the <var>stoppableExecutor</var> must <i>not</i> change
- * variables or data structures used by several threads or else the problems described in <a
+ * <strong>Note: Code executed in the <var>stoppableExecutor</var> must <i>not</i> change variables
+ * or data structures used by several threads or else the problems described in <a
  * href="http://java.sun.com/j2se/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html">"Why is
- * <code>Thread.stop()</code> deprecated?"</a> apply to your code! Watch out for static
- * thread-safe variables like e.g. the ones of type {@link ThreadLocal}!</strong>
+ * <code>Thread.stop()</code> deprecated?"</a> apply to your code! Watch out for static thread-safe
+ * variables like e.g. the ones of type {@link ThreadLocal}!</strong>
  * <p>
- * The <var>stoppableExecutor</var> is in general supposed to be used for time-consuming
- * algorithmic code which cannot be interrupted (because it doesn't check the thread's interrupt
- * state). The simplest case is one big algorithmic block which uses final variables of the caller
- * as input and delivers its result as return value:
+ * The <var>stoppableExecutor</var> is in general supposed to be used for time-consuming algorithmic
+ * code which cannot be interrupted (because it doesn't check the thread's interrupt state). The
+ * simplest case is one big algorithmic block which uses final variables of the caller as input and
+ * delivers its result as return value:
  * 
  * <pre>
  * public Double call(IStoppableExecutor&lt;Double&gt; stoppableExecutor)
@@ -93,7 +95,7 @@ import ch.systemsx.cisd.common.utilities.ITerminable;
  * 
  * @author Bernd Rinn
  */
-public final class TerminableCallable<V> implements Callable<V>, ITerminable
+public final class TerminableCallable<V> implements Callable<V>, ICallableNameProvider, ITerminable
 
 {
     /** A constant indicating not to wait and to return immediately. */
@@ -123,6 +125,8 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     /** The time (in milli-seconds) to wait for {@link #terminate()} to finish up. */
     private final long timeoutTerminateMillis;
 
+    private final String nameOrNull;
+
     /** Indicator for why the callable finished. */
     public enum FinishCause
     {
@@ -169,6 +173,14 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
         public V call(IStoppableExecutor<V> stoppableExecutor) throws Exception;
     }
 
+    /**
+     * A {@link Callable} that has available a {@link TerminableCallable.IStoppableExecutor} for
+     * running code that cannot be interrupted but stopped and does know its name.
+     */
+    public interface INamedCallable<V> extends ICallable<V>, ICallableNameProvider
+    {
+    }
+
     /**
      * A role that can perform a clean-up.
      */
@@ -176,9 +188,8 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     {
         /**
          * The method that is called whenever the
-         * {@link ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable#call(
-         * ch.systemsx.cisd.common.concurrent.TerminableCallable.IStoppableExecutor)} method
-         * finishes or terminates.
+         * {@link ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable#call(ch.systemsx.cisd.common.concurrent.TerminableCallable.IStoppableExecutor)}
+         * method finishes or terminates.
          * <p>
          * Note that this method is <i>always</i> called, no matter what the cause is. If you want
          * to perform clean up only for some causes, check <var>cause</var> first.
@@ -192,8 +203,7 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
          * operations that can fail with an exception.</strong>
          * 
          * @param cause The cause why the
-         *            {@link ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable#call(
-         *            ch.systemsx.cisd.common.concurrent.TerminableCallable.IStoppableExecutor)}
+         *            {@link ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable#call(ch.systemsx.cisd.common.concurrent.TerminableCallable.IStoppableExecutor)}
          *            method finished.
          */
         public void cleanUp(FinishCause cause);
@@ -212,9 +222,8 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
      * terminate the callable.
      * <p>
      * Convenience wrapper for
-     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, 
-     * ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)} with
-     * <var>waitInterruptMillis</var> set to {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} and
+     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)}
+     * with <var>waitInterruptMillis</var> set to {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} and
      * <var>timeoutTerminateMillis</var> set to {@link #WAIT_FOREVER_MILLIS}.
      */
     public static <V> TerminableCallable<V> create(ICallable<V> delegate)
@@ -223,15 +232,14 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     }
 
     /**
-     * Factory method that creates a {@link TerminableCallable} with a <var>delegateWithCleaner</var>
-     * which is also used to clean up after the call. It sets a time of
-     * {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} to wait for {@link Thread#interrupt()} to terminate
+     * Factory method that creates a {@link TerminableCallable} with a
+     * <var>delegateWithCleaner</var> which is also used to clean up after the call. It sets a time
+     * of {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} to wait for {@link Thread#interrupt()} to terminate
      * the callable.
      * <p>
      * Convenience wrapper for
-     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, 
-     * ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)} with
-     * <var>waitInterruptMillis</var> set to {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} and
+     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)}
+     * with <var>waitInterruptMillis</var> set to {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} and
      * <var>timeoutTerminateMillis</var> set to {@link #WAIT_FOREVER_MILLIS}.
      */
     public static <V> TerminableCallable<V> create(ICallableCleaner<V> delegateWithCleaner)
@@ -245,9 +253,8 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
      * separate <var>cleaner</var>.
      * <p>
      * Convenience wrapper for
-     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, 
-     * ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)} with
-     * <var>waitInterruptMillis</var> set to {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} and
+     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)}
+     * with <var>waitInterruptMillis</var> set to {@link #DEFAULT_WAIT_INTERRUPT_MILLIS} and
      * <var>timeoutTerminateMillis</var> set to {@link #WAIT_FOREVER_MILLIS}.
      */
     public static <V> TerminableCallable<V> create(ICallable<V> delegate, ICleaner cleaner)
@@ -273,8 +280,8 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     }
 
     /**
-     * Factory method that creates a {@link TerminableCallable} with a <var>delegate</var> that
-     * only runs code which is safe to stop.
+     * Factory method that creates a {@link TerminableCallable} with a <var>delegate</var> that only
+     * runs code which is safe to stop.
      * <p>
      * <strong>Note: Code executed in the <var>delegate</var> must <i>not</i> change variables or
      * data structures used by several threads or else the problems described in <a
@@ -313,6 +320,9 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
         this.cleanerOrNull = cleanerOrNull;
         this.waitInterruptMillis = waitInterruptMillis;
         this.timeoutTerminateMillis = timeoutTerminateMillis;
+        this.nameOrNull =
+                (delegate instanceof ICallableNameProvider) ? ((ICallableNameProvider) delegate)
+                        .getCallableName() : null;
     }
 
     private void cleanUp(Throwable throwableOrNull)
@@ -338,7 +348,8 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
         }
     }
 
-    private InterruptedException getOrCreateInterruptedException(InterruptedExceptionUnchecked stopEx)
+    private InterruptedException getOrCreateInterruptedException(
+            InterruptedExceptionUnchecked stopEx)
     {
         final InterruptedException causeOrNull = stopEx.getCause();
         return (causeOrNull != null) ? causeOrNull : new InterruptedException();
@@ -405,7 +416,7 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
      */
     public Runnable asRunnable()
     {
-        return new Runnable()
+        return new NamedRunnable()
             {
                 public void run()
                 {
@@ -417,9 +428,19 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
                         throw CheckedExceptionTunnel.wrapIfNecessary(ex);
                     }
                 }
+
+                public String getRunnableName()
+                {
+                    return getCallableName();
+                }
             };
     }
 
+    public String getCallableName()
+    {
+        return nameOrNull;
+    }
+
     /**
      * Returns <code>true</code> if the callable is currently running and <code>false</code>
      * otherwise.
@@ -436,7 +457,7 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     {
         return threadGuard.isCancelled();
     }
-    
+
     /**
      * Returns <code>true</code> if the callable has already started running.
      */
@@ -473,10 +494,9 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     /**
      * Cancels the callable if it is not yet running.
      * 
-     * @param mayInterruptIfRunning If <code>true</code> and the callable is running, interrupt
-     *            its thread. Otherwise, do nothing.
-     * @return <code>true</code>, if the callable is cancelled and <code>false</code>
-     *         otherwise.
+     * @param mayInterruptIfRunning If <code>true</code> and the callable is running, interrupt its
+     *            thread. Otherwise, do nothing.
+     * @return <code>true</code>, if the callable is cancelled and <code>false</code> otherwise.
      */
     public boolean cancel(boolean mayInterruptIfRunning)
     {
@@ -485,10 +505,10 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
 
     /**
      * Terminates this {@link TerminableCallable}. A convenience wrapper for
-     * {@link #terminate(long)} with <var>timeoutMillis</var> set to <var>timeoutTerminateMillis</var>
-     * as set in the factory method (see
-     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, 
-     * ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)}.
+     * {@link #terminate(long)} with <var>timeoutMillis</var> set to
+     * <var>timeoutTerminateMillis</var> as set in the factory method (see
+     * {@link #create(ch.systemsx.cisd.common.concurrent.TerminableCallable.ICallable, ch.systemsx.cisd.common.concurrent.TerminableCallable.ICleaner, long, long)}
+     * .
      * 
      * @return <code>true</code>, if the callable is confirmed to be terminated and cleaned up
      *         successfully in due time, or <code>false</code>, if a timeout has occurred.
@@ -500,11 +520,11 @@ public final class TerminableCallable<V> implements Callable<V>, ITerminable
     }
 
     /**
-     * Tries to terminate this {@link TerminableCallable}. Note that this is a synchronous call
-     * that returns only when either the callable has been terminated or finished or when a timeout
-     * has occurred. Note also that even when providing <var>timeoutMillis</var> as 0, this method
-     * may wait up to <var>waitInterruptMillis</var> milli-seconds for the
-     * {@link Thread#interrupt()} call to terminate the callable.
+     * Tries to terminate this {@link TerminableCallable}. Note that this is a synchronous call that
+     * returns only when either the callable has been terminated or finished or when a timeout has
+     * occurred. Note also that even when providing <var>timeoutMillis</var> as 0, this method may
+     * wait up to <var>waitInterruptMillis</var> milli-seconds for the {@link Thread#interrupt()}
+     * call to terminate the callable.
      * 
      * @param timeoutMillis The method will wait at most this time (in milli-seconds).
      * @return <code>true</code>, if the callable is confirmed to be terminated or finished, or
-- 
GitLab