Skip to content
Snippets Groups Projects
Commit 8e422585 authored by brinn's avatar brinn
Browse files

Support named callables.

SVN: 24031
parent 41e334c8
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment