All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.android.util.ContinuableFuture Maven / Gradle / Ivy

There is a newer version: 1.10.1
Show newest version
/*
 * Copyright (C) 2016 HaiYang Li
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.landawn.abacus.android.util;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import com.landawn.abacus.util.N;
import com.landawn.abacus.util.Result;
import com.landawn.abacus.util.Throwables;
import com.landawn.abacus.util.Tuple;
import com.landawn.abacus.util.Tuple.Tuple4;

// TODO: Auto-generated Javadoc
/**
 * 
* TP -> Thread Pool. * * @author Haiyang Li * @param * @since 0.8 */ public class ContinuableFuture implements Future { private static final Executor DEFAULT_EXECUTOR = Async.TP_EXECUTOR; final Future future; final List> upFutures; final Executor asyncExecutor; ContinuableFuture(final Future future) { this(future, null, null); } ContinuableFuture(final Future future, final List> upFutures, final Executor asyncExecutor) { this.future = future; this.upFutures = upFutures; this.asyncExecutor = asyncExecutor == null ? DEFAULT_EXECUTOR : asyncExecutor; } // public static ContinuableFuture run(final Throwables.Runnable action) { // return run(action, Async.SERIAL_EXECUTOR); // } // // public static ContinuableFuture run(final Try.Callable action) { // return run(action, Async.SERIAL_EXECUTOR); // } // // public static ContinuableFuture run(final Throwables.Runnable action, final Executor executor) { // final FutureTask futureTask = new FutureTask<>(action, null); // // executor.execute(futureTask); // // return new ContinuableFuture<>(futureTask, null, executor); // } // // public static ContinuableFuture run(final Try.Callable action, final Executor executor) { // final FutureTask futureTask = new FutureTask<>(action); // // executor.execute(futureTask); // // return new ContinuableFuture<>(futureTask, null, executor); // } /** * * @param * @param result * @return a ContinuableFuture which is already done by passing the result to it directly. */ public static ContinuableFuture completed(final T result) { return new ContinuableFuture<>(new Future() { @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return true; } @Override public T get() { return result; } @Override public T get(final long timeout, final TimeUnit unit) { return result; } }, null, Async.SERIAL_EXECUTOR); } /** * * @param * @param future * @return */ public static ContinuableFuture wrap(Future future) { return new ContinuableFuture<>(future); } /** * * @param mayInterruptIfRunning * @return true, if successful */ @Override public boolean cancel(boolean mayInterruptIfRunning) { return future.cancel(mayInterruptIfRunning); } /** * Checks if is cancelled. * * @return true, if is cancelled */ @Override public boolean isCancelled() { return future.isCancelled(); } /** * Cancel this future and all the previous stage future recursively. * * @param mayInterruptIfRunning * @return true, if successful */ public boolean cancelAll(boolean mayInterruptIfRunning) { boolean res = true; if (N.notNullOrEmpty(upFutures)) { for (ContinuableFuture preFuture : upFutures) { res = res & preFuture.cancelAll(mayInterruptIfRunning); } } return cancel(mayInterruptIfRunning) && res; } /** * Returns true if this future and all previous stage futures have been recursively cancelled, otherwise false is returned. * * @return true, if is all cancelled */ public boolean isAllCancelled() { boolean res = true; if (N.notNullOrEmpty(upFutures)) { for (ContinuableFuture preFuture : upFutures) { res = res & preFuture.isAllCancelled(); } } return isCancelled() && res; } /** * Checks if is done. * * @return true, if is done */ @Override public boolean isDone() { return future.isDone(); } /** * * @return * @throws InterruptedException the interrupted exception * @throws ExecutionException the execution exception */ @Override public T get() throws InterruptedException, ExecutionException { return future.get(); } /** * * @param timeout * @param unit * @return * @throws InterruptedException the interrupted exception * @throws ExecutionException the execution exception * @throws TimeoutException the timeout exception */ @Override public T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return future.get(timeout, unit); } /** * Gets the t. * * @return */ public Result gett() { try { return Result.of(get(), null); } catch (Exception e) { return Result.of(null, e); } } /** * Gets the t. * * @param timeout * @param unit * @return */ public Result gett(final long timeout, final TimeUnit unit) { try { return Result.of(get(timeout, unit), null); } catch (Exception e) { return Result.of(null, e); } } /** * Gets the now. * * @param defaultValue * @return */ public T getNow(T defaultValue) { if (isDone()) { try { return get(); } catch (InterruptedException | ExecutionException e) { throw N.toRuntimeException(e); } } return defaultValue; } /** * Gets the then apply. * * @param * @param * @param action * @return * @throws InterruptedException the interrupted exception * @throws ExecutionException the execution exception * @throws E the e */ public R getThenApply(final Throwables.Function action) throws InterruptedException, ExecutionException, E { return action.apply(get()); } /** * Gets the then apply. * * @param * @param * @param timeout * @param unit * @param action * @return * @throws InterruptedException the interrupted exception * @throws ExecutionException the execution exception * @throws TimeoutException the timeout exception * @throws E the e */ public R getThenApply(final long timeout, final TimeUnit unit, final Throwables.Function action) throws InterruptedException, ExecutionException, TimeoutException, E { return action.apply(get(timeout, unit)); } /** * Gets the then apply. * * @param * @param * @param action * @return * @throws E the e */ public R getThenApply(final Throwables.BiFunction action) throws E { final Result result = gett(); return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); } /** * Gets the then apply. * * @param * @param * @param timeout * @param unit * @param action * @return * @throws E the e */ public R getThenApply(final long timeout, final TimeUnit unit, final Throwables.BiFunction action) throws E { final Result result = gett(timeout, unit); return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); } /** * Gets the then accept. * * @param * @param action * @return * @throws InterruptedException the interrupted exception * @throws ExecutionException the execution exception * @throws E the e */ public void getThenAccept(final Throwables.Consumer action) throws InterruptedException, ExecutionException, E { action.accept(get()); } /** * Gets the then accept. * * @param * @param timeout * @param unit * @param action * @return * @throws InterruptedException the interrupted exception * @throws ExecutionException the execution exception * @throws TimeoutException the timeout exception * @throws E the e */ public void getThenAccept(final long timeout, final TimeUnit unit, final Throwables.Consumer action) throws InterruptedException, ExecutionException, TimeoutException, E { action.accept(get(timeout, unit)); } /** * Gets the then accept. * * @param * @param action * @return * @throws E the e */ public void getThenAccept(final Throwables.BiConsumer action) throws E { final Result result = gett(); action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); } /** * Gets the then accept. * * @param * @param timeout * @param unit * @param action * @return * @throws E the e */ public void getThenAccept(final long timeout, final TimeUnit unit, final Throwables.BiConsumer action) throws E { final Result result = gett(timeout, unit); action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); } /** * * @param * @param * @param func * @return */ public ContinuableFuture map(final Throwables.Function func) { return new ContinuableFuture(new Future() { @Override public boolean cancel(boolean mayInterruptIfRunning) { return ContinuableFuture.this.cancel(mayInterruptIfRunning); } @Override public boolean isCancelled() { return ContinuableFuture.this.isCancelled(); } @Override public boolean isDone() { return ContinuableFuture.this.isDone(); } @Override public U get() throws InterruptedException, ExecutionException { try { return func.apply(ContinuableFuture.this.get()); } catch (InterruptedException | ExecutionException e) { throw e; } catch (Exception e) { throw N.toRuntimeException(e); } } @Override public U get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { try { return func.apply(ContinuableFuture.this.get(timeout, unit)); } catch (InterruptedException | ExecutionException | TimeoutException e) { throw e; } catch (Exception e) { throw N.toRuntimeException(e); } } }, null, asyncExecutor) { @Override public boolean cancelAll(boolean mayInterruptIfRunning) { return ContinuableFuture.this.cancelAll(mayInterruptIfRunning); } @Override public boolean isAllCancelled() { return ContinuableFuture.this.isAllCancelled(); } }; } // ContinuableFuture thenApply(final BiFunction action) { // return new ContinuableFuture(new Future() { // @Override // public boolean cancel(boolean mayInterruptIfRunning) { // return future.cancel(mayInterruptIfRunning); // } // // @Override // public boolean isCancelled() { // return future.isCancelled(); // } // // @Override // public boolean isDone() { // return future.isDone(); // } // // @Override // public U get() throws InterruptedException, ExecutionException { // final Result result = gett(); // // return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); // } // // @Override // public U get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { // final Result result = gett(timeout, unit); // // return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); // } // }, null, asyncExecutor) { // @Override // public boolean cancelAll(boolean mayInterruptIfRunning) { // return super.cancelAll(mayInterruptIfRunning); // } // // @Override // public boolean isAllCancelled() { // return super.isAllCancelled(); // } // }; // } // public ContinuableFuture thenAccept(final Throwables.Consumer action) { // return thenApply(new Function() { // @Override // public Void apply(T t) { // action.accept(t); // return null; // } // }); // } // // public ContinuableFuture thenAccept(final Throwables.BiConsumer action) { // return thenApply(new BiFunction() { // @Override // public Void apply(T t, Exception e) { // action.accept(t, e); // return null; // } // }); // } // // public ContinuableFuture thenCombine(final ContinuableFuture other, final BiFunction action) { // return new ContinuableFuture(new Future() { // @Override // public boolean cancel(boolean mayInterruptIfRunning) { // return future.cancel(mayInterruptIfRunning) && other.future.cancel(mayInterruptIfRunning); // } // // @Override // public boolean isCancelled() { // return future.isCancelled() || other.future.isCancelled(); // } // // @Override // public boolean isDone() { // return future.isDone() && other.future.isDone(); // } // // @Override // public R get() throws InterruptedException, ExecutionException { // return action.apply(future.get(), other.future.get()); // } // // @Override // public R get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { // final long timeoutInMillis = unit.toMillis(timeout); // final long now = N.currentMillis(); // final long endTime = timeoutInMillis > Long.MAX_VALUE - now ? Long.MAX_VALUE : now + timeoutInMillis; // // final T result = future.get(timeout, unit); // final U otherResult = other.future.get(N.max(0, endTime - N.currentMillis()), TimeUnit.MILLISECONDS); // // return action.apply(result, otherResult); // } // }, null, asyncExecutor) { // @Override // public boolean cancelAll(boolean mayInterruptIfRunning) { // return super.cancelAll(mayInterruptIfRunning) && other.cancelAll(mayInterruptIfRunning); // } // // @Override // public boolean isAllCancelled() { // return super.isAllCancelled() && other.isAllCancelled(); // } // }; // } // // public ContinuableFuture thenCombine(final ContinuableFuture other, final Throwables.Function, R, E> action) { // return new ContinuableFuture(new Future() { // @Override // public boolean cancel(boolean mayInterruptIfRunning) { // return future.cancel(mayInterruptIfRunning) && other.future.cancel(mayInterruptIfRunning); // } // // @Override // public boolean isCancelled() { // return future.isCancelled() || other.future.isCancelled(); // } // // @Override // public boolean isDone() { // return future.isDone() && other.future.isDone(); // } // // @Override // public R get() throws InterruptedException, ExecutionException { // final Result result = gett(); // final Pair result2 = other.gett(); // // return action.apply(Tuple.of(result.orElseIfFailure(null), result.getExceptionIfPresent(), (U) result2.left, result2.right)); // } // // @Override // public R get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { // final long timeoutInMillis = unit.toMillis(timeout); // final long now = N.currentMillis(); // final long endTime = timeoutInMillis > Long.MAX_VALUE - now ? Long.MAX_VALUE : now + timeoutInMillis; // // final Result result = ContinuableFuture.this.gett(timeout, unit); // final Pair result2 = other.gett(N.max(0, endTime - N.currentMillis()), TimeUnit.MILLISECONDS); // // return action.apply(Tuple.of(result.orElseIfFailure(null), result.getExceptionIfPresent(), (U) result2.left, result2.right)); // } // }, null, asyncExecutor) { // @Override // public boolean cancelAll(boolean mayInterruptIfRunning) { // return super.cancelAll(mayInterruptIfRunning) && other.cancelAll(mayInterruptIfRunning); // } // // @Override // public boolean isAllCancelled() { // return super.isAllCancelled() && other.isAllCancelled(); // } // }; // } // // public ContinuableFuture thenAcceptBoth(final ContinuableFuture other, final BiConsumer action) { // return thenCombine(other, new BiFunction() { // @Override // public Void apply(T t, U u) { // action.accept(t, u); // return null; // } // }); // } // // public ContinuableFuture thenAcceptBoth(final ContinuableFuture other, final Throwables.Consumer, E> action) { // return thenCombine(other, new Function, Void>() { // @Override // public Void apply(Tuple4 t) { // action.accept(t); // return null; // } // }); // } /** * * @param * @param action * @return */ public ContinuableFuture thenRun(final Throwables.Runnable action) { return execute(new Callable() { @Override public Void call() throws Exception { get(); action.run(); return null; } }); } /** * * @param * @param action * @return */ public ContinuableFuture thenRun(final Throwables.Consumer action) { return execute(new Callable() { @Override public Void call() throws Exception { action.accept(get()); return null; } }); } /** * * @param * @param action * @return */ public ContinuableFuture thenRun(final Throwables.BiConsumer action) { return execute(new Callable() { @Override public Void call() throws Exception { final Result result = gett(); action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); return null; } }); } /** * * @param * @param action * @return */ public ContinuableFuture thenCall(final Callable action) { return execute(new Callable() { @Override public R call() throws Exception { get(); return action.call(); } }); } /** * * @param * @param * @param action * @return */ public ContinuableFuture thenCall(final Throwables.Function action) { return execute(new Callable() { @Override public R call() throws Exception { return action.apply(get()); } }); } /** * * @param * @param * @param action * @return */ public ContinuableFuture thenCall(final Throwables.BiFunction action) { return execute(new Callable() { @Override public R call() throws Exception { final Result result = gett(); return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); } }); } /** * Then run on UI. * * @param * @param action * @return */ public ContinuableFuture thenRunOnUI(final Throwables.Runnable action) { return thenUseUIExecutor().thenRun(action); } /** * Then run on UI. * * @param * @param action * @return */ public ContinuableFuture thenRunOnUI(final Throwables.Consumer action) { return thenUseUIExecutor().thenRun(action); } /** * Then run on UI. * * @param * @param action * @return */ public ContinuableFuture thenRunOnUI(final Throwables.BiConsumer action) { return thenUseUIExecutor().thenRun(action); } /** * Then call on UI. * * @param * @param action * @return */ public ContinuableFuture thenCallOnUI(final Callable action) { return thenUseUIExecutor().thenCall(action); } /** * Then call on UI. * * @param * @param * @param action * @return */ public ContinuableFuture thenCallOnUI(final Throwables.Function action) { return thenUseUIExecutor().thenCall(action); } /** * Then call on UI. * * @param * @param * @param action * @return */ public ContinuableFuture thenCallOnUI(final Throwables.BiFunction action) { return thenUseUIExecutor().thenCall(action); } /** * Then run by TP. * * @param * @param action * @return */ public ContinuableFuture thenRunByTP(final Throwables.Runnable action) { return thenUseTPExecutor().thenRun(action); } /** * Then run by TP. * * @param * @param action * @return */ public ContinuableFuture thenRunByTP(final Throwables.Consumer action) { return thenUseTPExecutor().thenRun(action); } /** * Then run by TP. * * @param * @param action * @return */ public ContinuableFuture thenRunByTP(final Throwables.BiConsumer action) { return thenUseTPExecutor().thenRun(action); } /** * Then call by TP. * * @param * @param action * @return */ public ContinuableFuture thenCallByTP(final Callable action) { return thenUseTPExecutor().thenCall(action); } /** * Then call by TP. * * @param * @param * @param action * @return */ public ContinuableFuture thenCallByTP(final Throwables.Function action) { return thenUseTPExecutor().thenCall(action); } /** * Then call by TP. * * @param * @param * @param action * @return */ public ContinuableFuture thenCallByTP(final Throwables.BiFunction action) { return thenUseTPExecutor().thenCall(action); } /** * Run after both. * * @param * @param other * @param action * @return */ public ContinuableFuture runAfterBoth(final ContinuableFuture other, final Throwables.Runnable action) { return execute(new Callable() { @Override public Void call() throws Exception { get(); other.get(); action.run(); return null; } }, other); } /** * Run after both. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runAfterBoth(final ContinuableFuture other, final Throwables.BiConsumer action) { return execute(new Callable() { @Override public Void call() throws Exception { action.accept(get(), other.get()); return null; } }, other); } /** * Run after both. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runAfterBoth(final ContinuableFuture other, final Throwables.Consumer, E> action) { return execute(new Callable() { @Override public Void call() throws Exception { final Result result = gett(); final Result result2 = other.gett(); action.accept( Tuple.of(result.orElseIfFailure(null), result.getExceptionIfPresent(), result2.orElseIfFailure(null), result2.getExceptionIfPresent())); return null; } }, other); } /** * Call after both. * * @param * @param other * @param action * @return */ public ContinuableFuture callAfterBoth(final ContinuableFuture other, final Callable action) { return execute(new Callable() { @Override public R call() throws Exception { get(); other.get(); return action.call(); } }, other); } /** * Call after both. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callAfterBoth(final ContinuableFuture other, final Throwables.BiFunction action) { return execute(new Callable() { @Override public R call() throws Exception { return action.apply(get(), other.get()); } }, other); } /** * Call after both. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callAfterBoth(final ContinuableFuture other, final Throwables.Function, R, E> action) { return execute(new Callable() { @Override public R call() throws Exception { final Result result = gett(); final Result result2 = other.gett(); return action.apply( Tuple.of(result.orElseIfFailure(null), result.getExceptionIfPresent(), result2.orElseIfFailure(null), result2.getExceptionIfPresent())); } }, other); } /** * Run on UI after both. * * @param * @param other * @param action * @return */ public ContinuableFuture runOnUIAfterBoth(final ContinuableFuture other, final Throwables.Runnable action) { return thenUseUIExecutor().runAfterBoth(other, action); } /** * Run on UI after both. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runOnUIAfterBoth(final ContinuableFuture other, final Throwables.BiConsumer action) { return thenUseUIExecutor().runAfterBoth(other, action); } /** * Run on UI after both. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runOnUIAfterBoth(final ContinuableFuture other, final Throwables.Consumer, E> action) { return thenUseUIExecutor().runAfterBoth(other, action); } /** * Call on UI after both. * * @param * @param other * @param action * @return */ public ContinuableFuture callOnUIAfterBoth(final ContinuableFuture other, final Callable action) { return thenUseUIExecutor().callAfterBoth(other, action); } /** * Call on UI after both. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callOnUIAfterBoth(final ContinuableFuture other, final Throwables.BiFunction action) { return thenUseUIExecutor().callAfterBoth(other, action); } /** * Call on UI after both. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callOnUIAfterBoth(final ContinuableFuture other, final Throwables.Function, R, E> action) { return thenUseUIExecutor().callAfterBoth(other, action); } /** * Run by TP after both. * * @param * @param other * @param action * @return */ public ContinuableFuture runByTPAfterBoth(final ContinuableFuture other, final Throwables.Runnable action) { return thenUseTPExecutor().runAfterBoth(other, action); } /** * Run by TP after both. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runByTPAfterBoth(final ContinuableFuture other, final Throwables.BiConsumer action) { return thenUseTPExecutor().runAfterBoth(other, action); } /** * Run by TP after both. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runByTPAfterBoth(final ContinuableFuture other, final Throwables.Consumer, E> action) { return thenUseTPExecutor().runAfterBoth(other, action); } /** * Call by TP after both. * * @param * @param other * @param action * @return */ public ContinuableFuture callByTPAfterBoth(final ContinuableFuture other, final Callable action) { return thenUseTPExecutor().callAfterBoth(other, action); } /** * Call by TP after both. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callByTPAfterBoth(final ContinuableFuture other, final Throwables.BiFunction action) { return thenUseTPExecutor().callAfterBoth(other, action); } /** * Call by TP after both. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callByTPAfterBoth(final ContinuableFuture other, final Throwables.Function, R, E> action) { return thenUseTPExecutor().callAfterBoth(other, action); } /** * Run after either. * * @param * @param other * @param action * @return */ public ContinuableFuture runAfterEither(final ContinuableFuture other, final Throwables.Runnable action) { return execute(new Callable() { @Override public Void call() throws Exception { Futures.anyOf(N.asList(ContinuableFuture.this, other)).get(); action.run(); return null; } }, other); } /** * Run after either. * * @param * @param other * @param action * @return */ public ContinuableFuture runAfterEither(final ContinuableFuture other, final Throwables.Consumer action) { return execute(new Callable() { @Override public Void call() throws Exception { final T result = Futures.anyOf(N.asList(ContinuableFuture.this, other)).get(); action.accept(result); return null; } }, other); } /** * Run after either. * * @param * @param other * @param action * @return */ public ContinuableFuture runAfterEither(final ContinuableFuture other, final Throwables.BiConsumer action) { return execute(new Callable() { @Override public Void call() throws Exception { final Result result = Futures.anyOf(N.asList(ContinuableFuture.this, other)).gett(); action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); return null; } }, other); } /** * Call after either. * * @param * @param other * @param action * @return */ public ContinuableFuture callAfterEither(final ContinuableFuture other, final Callable action) { return execute(new Callable() { @Override public R call() throws Exception { Futures.anyOf(N.asList(ContinuableFuture.this, other)).get(); return action.call(); } }, other); } /** * Call after either. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture callAfterEither(final ContinuableFuture other, final Throwables.Function action) { return execute(new Callable() { @Override public R call() throws Exception { final T result = Futures.anyOf(N.asList(ContinuableFuture.this, other)).get(); return action.apply(result); } }, other); } /** * Call after either. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture callAfterEither(final ContinuableFuture other, final Throwables.BiFunction action) { return execute(new Callable() { @Override public R call() throws Exception { final Result result = Futures.anyOf(N.asList(ContinuableFuture.this, other)).gett(); return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); } }, other); } /** * Run on UI after either. * * @param * @param other * @param action * @return */ public ContinuableFuture runOnUIAfterEither(final ContinuableFuture other, final Throwables.Runnable action) { return thenUseUIExecutor().runAfterEither(other, action); } /** * Run on UI after either. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runOnUIAfterEither(final ContinuableFuture other, final Throwables.Consumer action) { return thenUseUIExecutor().runAfterEither(other, action); } /** * Run on UI after either. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runOnUIAfterEither(final ContinuableFuture other, final Throwables.BiConsumer action) { return thenUseUIExecutor().runAfterEither(other, action); } /** * Call on UI after either. * * @param * @param other * @param action * @return */ public ContinuableFuture callOnUIAfterEither(final ContinuableFuture other, final Callable action) { return thenUseUIExecutor().callAfterEither(other, action); } /** * Call on UI after either. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callOnUIAfterEither(final ContinuableFuture other, final Throwables.Function action) { return thenUseUIExecutor().callAfterEither(other, action); } /** * Call on UI after either. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callOnUIAfterEither(final ContinuableFuture other, final Throwables.BiFunction action) { return thenUseUIExecutor().callAfterEither(other, action); } /** * Run by TP after either. * * @param * @param other * @param action * @return */ public ContinuableFuture runByTPAfterEither(final ContinuableFuture other, final Throwables.Runnable action) { return thenUseTPExecutor().runAfterEither(other, action); } /** * Run by TP after either. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runByTPAfterEither(final ContinuableFuture other, final Throwables.Consumer action) { return thenUseTPExecutor().runAfterEither(other, action); } /** * Run by TP after either. * * @param * @param * @param other * @param action * @return */ public ContinuableFuture runByTPAfterEither(final ContinuableFuture other, final Throwables.BiConsumer action) { return thenUseTPExecutor().runAfterEither(other, action); } /** * Call by TP after either. * * @param * @param other * @param action * @return */ public ContinuableFuture callByTPAfterEither(final ContinuableFuture other, final Callable action) { return thenUseTPExecutor().callAfterEither(other, action); } /** * Call by TP after either. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callByTPAfterEither(final ContinuableFuture other, final Throwables.Function action) { return thenUseTPExecutor().callAfterEither(other, action); } /** * Call by TP after either. * * @param * @param * @param * @param other * @param action * @return */ public ContinuableFuture callByTPAfterEither(final ContinuableFuture other, final Throwables.BiFunction action) { return thenUseTPExecutor().callAfterEither(other, action); } // /** // * Returns a new ContinuableFuture that, when either this or the // * other given ContinuableFuture complete normally. If both of the given // * ContinuableFutures complete exceptionally, then the returned // * ContinuableFuture also does so. // * // * @param other // * @param action // * @return // */ // public ContinuableFuture applyToEither(final ContinuableFuture other, final Function action) { // return Futures.anyOf(N.asList(this, other)).thenApply(action); // } // // /** // * Returns a new ContinuableFuture that, when either this or the // * other given ContinuableFuture complete normally. If both of the given // * ContinuableFutures complete exceptionally, then the returned // * ContinuableFuture also does so. // * // * @param other // * @param action // * @return // */ // public ContinuableFuture acceptEither(final ContinuableFuture other, final Throwables.Consumer action) { // return Futures.anyOf(N.asList(this, other)).thenAccept(action); // } // /** // * Returns a new ContinuableFuture that, when this ContinuableFuture completes // * exceptionally, is executed with this ContinuableFuture's exception as the // * argument to the supplied function. Otherwise, if this ContinuableFuture // * completes normally, then the returned ContinuableFuture also completes // * normally with the same value. // * // * @param action // * @return // */ // public ContinuableFuture exceptionally(final Function action) { // return new ContinuableFuture(new Future() { // @Override // public boolean cancel(boolean mayInterruptIfRunning) { // return future.cancel(mayInterruptIfRunning); // } // // @Override // public boolean isCancelled() { // return future.isCancelled(); // } // // @Override // public boolean isDone() { // return future.isDone(); // } // // @Override // public T get() throws InterruptedException, ExecutionException { // try { // return future.get(); // } catch (Exception e) { // return action.apply(e); // } // } // // @Override // public T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { // try { // return future.get(timeout, unit); // } catch (Exception e) { // return action.apply(e); // } // } // }, null, asyncExecutor) { // @Override // public boolean cancelAll(boolean mayInterruptIfRunning) { // return super.cancelAll(mayInterruptIfRunning); // } // // @Override // public boolean isAllCancelled() { // return super.isAllCancelled(); // } // }; // } // public ContinuableFuture whenComplete(final BiConsumer action) { // return new ContinuableFuture<>(new Future() { // @Override // public boolean cancel(boolean mayInterruptIfRunning) { // return future.cancel(mayInterruptIfRunning); // } // // @Override // public boolean isCancelled() { // return future.isCancelled(); // } // // @Override // public boolean isDone() { // return future.isDone(); // } // // @Override // public T get() throws InterruptedException, ExecutionException { // final Result result = gett(); // // if (result.right != null) { // try { // action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); // } catch (Exception e) { // // ignore. // } // // if (result.right instanceof InterruptedException) { // throw ((InterruptedException) result.right); // } else if (result.right instanceof ExecutionException) { // throw ((ExecutionException) result.right); // } else { // throw N.toRuntimeException(result.right); // } // } else { // action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); // return result.left; // } // } // // @Override // public T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { // final Result result = gett(timeout, unit); // // if (result.right != null) { // try { // action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); // } catch (Exception e) { // // ignore. // } // // if (result.right instanceof InterruptedException) { // throw ((InterruptedException) result.right); // } else if (result.right instanceof ExecutionException) { // throw ((ExecutionException) result.right); // } else { // throw N.toRuntimeException(result.right); // } // } else { // action.accept(result.orElseIfFailure(null), result.getExceptionIfPresent()); // return result.left; // } // } // }, asyncExecutor); // } // // public ContinuableFuture handle(final BiFunction action) { // return new ContinuableFuture<>(new Future() { // @Override // public boolean cancel(boolean mayInterruptIfRunning) { // return future.cancel(mayInterruptIfRunning); // } // // @Override // public boolean isCancelled() { // return future.isCancelled(); // } // // @Override // public boolean isDone() { // return future.isDone(); // } // // @Override // public U get() throws InterruptedException, ExecutionException { // final Result result = gett(); // return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); // } // // @Override // public U get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { // final Result result = gett(timeout, unit); // return action.apply(result.orElseIfFailure(null), result.getExceptionIfPresent()); // } // }, asyncExecutor); // } /** * * @param * @param command * @return */ private ContinuableFuture execute(final Callable command) { return execute(command, null); } /** * * @param * @param command * @param other * @return */ private ContinuableFuture execute(final Callable command, final ContinuableFuture other) { return execute(new FutureTask<>(command), other); } /** * * @param * @param futureTask * @param other * @return */ private ContinuableFuture execute(final FutureTask futureTask, final ContinuableFuture other) { asyncExecutor.execute(futureTask); @SuppressWarnings("rawtypes") final List> upFutures = other == null ? (List) Arrays.asList(this) : Arrays.asList(this, other); return new ContinuableFuture<>(futureTask, upFutures, asyncExecutor); } /** * * @param delay * @param unit * @return */ public ContinuableFuture thenDelay(long delay, TimeUnit unit) { if (delay <= 0) { return this; } return with(asyncExecutor, delay, unit); } /** * * @param executor * @return */ public ContinuableFuture thenUse(Executor executor) { return with(executor, 0, TimeUnit.MILLISECONDS); } /** * * @param executor * @param delay * @param unit * @return */ @Deprecated ContinuableFuture with(final Executor executor, final long delay, final TimeUnit unit) { N.checkArgNotNull(executor); return new ContinuableFuture(new Future() { private final long delayInMillis = unit.toMillis(delay); private final long startTime = System.currentTimeMillis(); private volatile boolean isDelayed = false; @Override public boolean cancel(boolean mayInterruptIfRunning) { return future.cancel(mayInterruptIfRunning); } @Override public boolean isCancelled() { return future.isCancelled(); } @Override public boolean isDone() { boolean isDone = future.isDone(); if (isDone) { delay(); } return isDone; } @Override public T get() throws InterruptedException, ExecutionException { delay(); return future.get(); } @Override public T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { delay(); return future.get(timeout, unit); } private void delay() { if (isDelayed == false) { isDelayed = true; N.sleepUninterruptibly(delayInMillis - (System.currentTimeMillis() - startTime)); } } }, null, executor) { @Override public boolean cancelAll(boolean mayInterruptIfRunning) { return super.cancelAll(mayInterruptIfRunning); } @Override public boolean isAllCancelled() { return super.isAllCancelled(); } }; } /** * Then use UI executor. * * @return */ public ContinuableFuture thenUseUIExecutor() { return thenUse(Async.UI_EXECUTOR); } /** * Then use serial executor. * * @return */ public ContinuableFuture thenUseSerialExecutor() { return thenUse(Async.SERIAL_EXECUTOR); } /** * With Thread Pool Executor. * * @return */ public ContinuableFuture thenUseTPExecutor() { return thenUse(Async.TP_EXECUTOR); } }