package edu.ualberta.med.biobank.mvp.action; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import edu.ualberta.med.biobank.common.action.Action; import edu.ualberta.med.biobank.common.action.ActionCallback; import edu.ualberta.med.biobank.common.action.ActionResult; import edu.ualberta.med.biobank.common.action.Dispatcher; public abstract class AbstractDispatcher implements Dispatcher { // TODO: need to shut this down? expose method to do so? private final ExecutorService pool = Executors.newFixedThreadPool(10); @Override public <T extends ActionResult> T exec(Action<T> action) { T result = null; try { result = doExec(action); } catch (Exception e) { // TODO: handle this better by (1) declaring thrown exception(s)? throw new RuntimeException(e); } return result; } @Override public <T extends ActionResult> Future<T> asyncExec(final Action<T> action, final ActionCallback<T> callback) { Future<T> future = pool.submit(new Callable<T>() { @Override public T call() { T result = null; try { result = doExec(action); callback.onSuccess(result); } catch (Throwable caught) { callback.onFailure(caught); } return result; } }); // TODO: if future.cancel() is called, then will onFailure() be called? // May need to listen for an interrupt then call onFailure(). return future; } protected abstract <T extends ActionResult> T doExec(Action<T> action) throws Exception; }