com.landawn.abacus.android.util.ContinuableFuture Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-android Show documentation
Show all versions of abacus-android Show documentation
A general and simple library for Android
/*
* 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 super T, R, E> 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 super T, R, E> 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 super T, ? super Exception, R, E> 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 super T, ? super Exception, R, E> 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 super T, E> 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 super T, E> 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 super T, ? super Exception, E> 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 super T, ? super Exception, E> 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 super T, U, E> 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 super T, Exception, U> 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 super T, E> action) {
// return thenApply(new Function() {
// @Override
// public Void apply(T t) {
// action.accept(t);
// return null;
// }
// });
// }
//
// public ContinuableFuture thenAccept(final Throwables.BiConsumer super T, Exception, E> 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 super T, ? super U, R> 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 super Tuple4, 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 super T, ? super U> 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 super Tuple4, 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 super T, E> 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 super T, ? super Exception, E> 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 super T, R, E> 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 super T, ? super Exception, R, E> 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 super T, E> action) {
return thenUseUIExecutor().thenRun(action);
}
/**
* Then run on UI.
*
* @param
* @param action
* @return
*/
public ContinuableFuture thenRunOnUI(final Throwables.BiConsumer super T, ? super Exception, E> 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 super T, R, E> action) {
return thenUseUIExecutor().thenCall(action);
}
/**
* Then call on UI.
*
* @param
* @param
* @param action
* @return
*/
public ContinuableFuture thenCallOnUI(final Throwables.BiFunction super T, ? super Exception, R, E> 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 super T, E> action) {
return thenUseTPExecutor().thenRun(action);
}
/**
* Then run by TP.
*
* @param
* @param action
* @return
*/
public ContinuableFuture thenRunByTP(final Throwables.BiConsumer super T, ? super Exception, E> 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 super T, R, E> action) {
return thenUseTPExecutor().thenCall(action);
}
/**
* Then call by TP.
*
* @param
* @param
* @param action
* @return
*/
public ContinuableFuture thenCallByTP(final Throwables.BiFunction super T, ? super Exception, R, E> 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 super T, ? super U, E> 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 super Tuple4, 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 super T, ? super U, R, E> 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 super Tuple4, 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 super T, ? super U, E> 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 super Tuple4, 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 super T, ? super U, R, E> 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 super Tuple4, 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