package net.jxta.impl.util.threads;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
/**
* Callable instance which will execute the wrapped Callable on the
* target ExecutorService instance when it executes, thereby forwarding
* execution to the target ExecutorService.
*
* @param <V> return type of the callable function
*/
public class ProxiedCallable<V>
implements Callable<V> {
/**
* Wrapped executor service instance.
*/
private final ExecutorService executor;
/**
* Wrapped callable.
*/
private final Callable<V> callable;
/**
* ProxiedScheduleFuture instance to pass our future instance to. We
* wait for this to be provided to us before executing our task.
*/
private ProxiedScheduledFuture<V> futureProxy;
///////////////////////////////////////////////////////////////////////////
// Constructor:
/**
* Creates a new proxied Callable instance.
*
* @param targetExecutor executor to run callable on
* @param targetCallable callable to execute
*/
public ProxiedCallable(
final ExecutorService targetExecutor,
final Callable<V> targetCallable) {
executor = targetExecutor;
callable = targetCallable;
}
///////////////////////////////////////////////////////////////////////////
// Callable interface methods:
/**
* {@inheritDoc}
*
* This implementation is equivalent to calling
* <code>targetExecutor.submit(targetCallable).get()</code> when this
* method is called.
*
* @throws Exception if the callable throws an exception during execution
*/
public V call() throws Exception {
Future<V> future = executor.submit(callable);
synchronized(this) {
while(futureProxy == null) {
wait();
}
futureProxy.setFuture(future);
}
// This result isn't used anywhere.
return null;
}
///////////////////////////////////////////////////////////////////////////
// Package methods:
/**
* Sets the scheduled future proxy that we should contact and provide
* the actual future instance to when we execute.
*
* @param proxy schedule future instance
*/
void setProxiedScheduledFuture(final ProxiedScheduledFuture<V> proxy) {
synchronized(this) {
if (futureProxy == null) {
futureProxy = proxy;
} else {
throw(new IllegalStateException(
"Proxy instance already set"));
}
notifyAll();
}
}
}