package org.threadly.concurrent.future;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.threadly.util.ArgumentVerifier;
/**
* This class is the adapter between a {@link FutureCallback} and a {@link Runnable}. Allowing
* you to supply this implementation as a Runnable as a listener into a {@link ListenableFuture}
* and have it convert the future's result into calls into a {@link FutureCallback}.
* <p>
* Instead of constructing this class, it is usually much easier to call into
* {@link ListenableFuture#addCallback(FutureCallback)}.
*
* @since 3.2.0
* @param <T> The result object type returned by this future
*/
public class RunnableFutureCallbackAdapter<T> implements Runnable {
protected final Future<T> future;
protected final FutureCallback<? super T> callback;
/**
* Constructs a new {@link RunnableFutureCallbackAdapter}.
*
* @param future Future to get result or error from
* @param callback Callback to call into once future has completed
*/
public RunnableFutureCallbackAdapter(Future<T> future, FutureCallback<? super T> callback) {
ArgumentVerifier.assertNotNull(future, "future");
ArgumentVerifier.assertNotNull(callback, "callback");
this.future = future;
this.callback = callback;
}
@Override
public void run() {
try {
T result = future.get();
callback.handleResult(result);
} catch (InterruptedException e) {
// will not be possible if provided as a listener to a ListenableFuture
Thread.currentThread().interrupt();
callback.handleFailure(e);
throw new RuntimeException(e);
} catch (ExecutionException e) {
callback.handleFailure(e.getCause());
} catch (CancellationException e) {
callback.handleFailure(e);
}
}
}