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<Double> 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