com.landawn.abacus.util.ContinuableFuture Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-common Show documentation
Show all versions of abacus-common Show documentation
A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.
/*
* 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.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.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.util.Tuple.Tuple4;
/**
*
* @author Haiyang Li
* @param
* @see https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ContinuableFuture.html
* @since 0.8
* @see Futures
*/
public class ContinuableFuture implements Future {
static final Logger logger = LoggerFactory.getLogger(ContinuableFuture.class);
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 ? N.ASYNC_EXECUTOR.getExecutor() : asyncExecutor;
}
/**
*
* @param action
* @return
* @see N#asyncExecute(Throwables.Runnable)
*/
public static ContinuableFuture run(final Throwables.Runnable extends Exception> action) {
return run(action, N.ASYNC_EXECUTOR.getExecutor());
}
/**
*
* @param action
* @param executor
* @return
*/
public static ContinuableFuture run(final Throwables.Runnable extends Exception> action, final Executor executor) {
final FutureTask futureTask = new FutureTask<>(() -> {
action.run();
return null;
});
executor.execute(futureTask);
return new ContinuableFuture<>(futureTask, null, executor);
}
/**
*
*
* @param
* @param action
* @return
* @see N#asyncExecute(Callable)
*/
public static ContinuableFuture call(final Callable action) {
return call(action, N.ASYNC_EXECUTOR.getExecutor());
}
/**
*
*
* @param
* @param action
* @param executor
* @return
*/
public static ContinuableFuture call(final 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, N.ASYNC_EXECUTOR.getExecutor());
}
/**
*
* @param
* @param future
* @return
*/
public static ContinuableFuture wrap(Future future) {
return new ContinuableFuture<>(future);
}
/**
*
* @param mayInterruptIfRunning
* @return
*/
@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
*/
public boolean cancelAll(boolean mayInterruptIfRunning) {
boolean res = true;
if (N.notEmpty(upFutures)) {
for (ContinuableFuture> preFuture : upFutures) {
res = res & preFuture.cancelAll(mayInterruptIfRunning); //NOSONAR
}
}
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() {
if (N.notEmpty(upFutures)) {
for (ContinuableFuture> preFuture : upFutures) {
if (preFuture.isAllCancelled()) {
return false;
}
}
}
return isCancelled();
}
/**
* 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
* @throws InterruptedException the interrupted exception
* @throws ExecutionException the execution exception
*/
public T getNow(T defaultValue) throws InterruptedException, ExecutionException {
if (isDone()) {
return get();
}
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 U getThenApply(final Throwables.Function super T, U, 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 U getThenApply(final long timeout, final TimeUnit unit, final Throwables.Function super T, U, 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 U getThenApply(final Throwables.BiFunction super T, ? super Exception, U, E> action) throws E {
final Result result = gett();
return action.apply(result.orElseIfFailure(null), result.getException());
}
/**
* Gets the then apply.
*
* @param
* @param
* @param timeout
* @param unit
* @param action
* @return
* @throws E the e
*/
public U getThenApply(final long timeout, final TimeUnit unit,
final Throwables.BiFunction super T, ? super Exception, U, E> action) throws E {
final Result result = gett(timeout, unit);
return action.apply(result.orElseIfFailure(null), result.getException());
}
/**
* Gets the then accept.
*
* @param
* @param action
* @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
* @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
* @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.getException());
}
/**
* Gets the then accept.
*
* @param
* @param timeout
* @param unit
* @param action
* @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.getException());
}
// public void complete() throws InterruptedException, ExecutionException {
// get();
// }
//
// public void complete(Consumer super T> action) {
// try {
// action.accept(get());
// } catch (InterruptedException | ExecutionException e) {
// throw ExceptionUtil.toRuntimeException(e);
// }
// }
//
// public void complete(BiConsumer super T, ? super Exception> action) {
// final Result result = gett();
// action.accept(result.orElse(null), result.getException());
// }
/**
*
* @param
* @param func
* @return
*/
public ContinuableFuture map(final Throwables.Function super T, ? extends U, ? extends Exception> 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 {
final T ret = ContinuableFuture.this.get();
try {
return func.apply(ret);
} catch (Exception e) {
throw ExceptionUtil.toRuntimeException(e);
}
}
@Override
public U get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
final T ret = ContinuableFuture.this.get(timeout, unit);
try {
return func.apply(ret);
} catch (Exception e) {
throw ExceptionUtil.toRuntimeException(e);
}
}
}, null, asyncExecutor) {
@Override
public boolean cancelAll(boolean mayInterruptIfRunning) {
return ContinuableFuture.this.cancelAll(mayInterruptIfRunning);
}
@Override
public boolean isAllCancelled() {
return ContinuableFuture.this.isAllCancelled();
}
};
}
// public ContinuableFuture thenApply(final BiFunction super T, ? super 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.orElse(null), result.getException());
// }
//
// @Override
// public U get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
// final Result result = gett(timeout, unit);
// return action.apply(result.orElse(null), result.getException());
// }
// }, null, asyncExecutor) {
// @Override
// public boolean cancelAll(boolean mayInterruptIfRunning) {
// return super.cancelAll(mayInterruptIfRunning);
// }
//
// @Override
// public boolean isAllCancelled() {
// return super.isAllCancelled();
// }
// };
// }
// public ContinuableFuture thenAccept(final Consumer super T> action) {
// return thenApply(new Function() {
// @Override
// public Void apply(T t) {
// action.accept(t);
// return null;
// }
// });
// }
//
// public ContinuableFuture thenAccept(final BiConsumer super T, ? super Exception> action) {
// return thenApply(new BiFunction() {
// @Override
// public Void apply(T t, ? super Exception e) {
// action.accept(t, e);
// return null;
// }
// });
// }
//
// public ContinuableFuture thenCombine(final ContinuableFuture other, final BiFunction super T, ? super U, ? extends 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 Function super Tuple4, ? extends 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 {
// final Result result = gett();
// final Pair result2 = other.gett();
//
// return action.apply(Tuple.of(result.orElse(null), result.getException(), (U) result2.orElse(null), result2.getException()));
// }
//
// @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.orElse(null), result.getException(), (U) result2.orElse(null), result2.getException()));
// }
// }, 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 Consumer super Tuple4> action) {
// return thenCombine(other, new Function, Void>() {
// @Override
// public Void apply(Tuple4 t) {
// action.accept(t);
// return null;
// }
// });
// }
/**
*
* @param action
* @return
*/
public ContinuableFuture thenRun(final Throwables.Runnable extends Exception> action) {
return execute(() -> {
get();
action.run();
return null;
});
}
/**
*
* @param action
* @return
*/
public ContinuableFuture thenRun(final Throwables.Consumer super T, ? extends Exception> action) {
return execute(() -> {
action.accept(get());
return null;
});
}
/**
*
* @param action
* @return
*/
public ContinuableFuture thenRun(final Throwables.BiConsumer super T, ? super Exception, ? extends Exception> action) {
return execute(() -> {
final Result result = gett();
action.accept(result.orElseIfFailure(null), result.getException());
return null;
});
}
/**
*
*
* @param
* @param action
* @return
*/
public ContinuableFuture thenCall(final Callable action) {
return execute(() -> {
get();
return action.call();
});
}
/**
*
* @param
* @param action
* @return
*/
public ContinuableFuture thenCall(final Throwables.Function super T, ? extends R, ? extends Exception> action) {
return execute(() -> action.apply(get()));
}
/**
*
* @param
* @param action
* @return
*/
public ContinuableFuture thenCall(final Throwables.BiFunction super T, ? super Exception, ? extends R, ? extends Exception> action) {
return execute(() -> {
final Result result = gett();
return action.apply(result.orElseIfFailure(null), result.getException());
});
}
/**
* Run after both.
*
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterBoth(final ContinuableFuture> other, final Throwables.Runnable extends Exception> action) {
return execute(() -> {
get();
other.get();
action.run();
return null;
}, other);
}
/**
* Run after both.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterBoth(final ContinuableFuture other,
final Throwables.BiConsumer super T, ? super U, ? extends Exception> action) {
return execute(() -> {
action.accept(get(), other.get());
return null;
}, other);
}
/**
* Run after both.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterBoth(final ContinuableFuture other,
final Throwables.Consumer super Tuple4, ? extends Exception> action) {
return execute(() -> {
final Result result = gett();
final Result result2 = other.gett();
action.accept(Tuple.of(result.orElseIfFailure(null), result.getException(), result2.orElseIfFailure(null), result2.getException()));
return null;
}, other);
}
/**
* Run after both.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterBoth(final ContinuableFuture other,
final Throwables.QuadConsumer action) {
return execute(() -> {
final Result result = gett();
final Result result2 = other.gett();
action.accept(result.orElseIfFailure(null), result.getException(), result2.orElseIfFailure(null), result2.getException());
return null;
}, other);
}
/**
* Call after both.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterBoth(final ContinuableFuture> other, final Callable action) {
return execute(() -> {
get();
other.get();
return action.call();
}, other);
}
/**
* Call after both.
*
* @param
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterBoth(final ContinuableFuture other,
final Throwables.BiFunction super T, ? super U, ? extends R, ? extends Exception> action) {
return execute(() -> action.apply(get(), other.get()), other);
}
/**
* Call after both.
*
* @param
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterBoth(final ContinuableFuture other,
final Throwables.Function super Tuple4, ? extends R, ? extends Exception> action) {
return execute(() -> {
final Result result = gett();
final Result result2 = other.gett();
return action.apply(Tuple.of(result.orElseIfFailure(null), result.getException(), result2.orElseIfFailure(null), result2.getException()));
}, other);
}
/**
* Call after both.
*
* @param
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterBoth(final ContinuableFuture other,
final Throwables.QuadFunction action) {
return execute(() -> {
final Result result = gett();
final Result result2 = other.gett();
return action.apply(result.orElseIfFailure(null), result.getException(), result2.orElseIfFailure(null), result2.getException());
}, other);
}
/**
* Run after either.
*
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterEither(final ContinuableFuture> other, final Throwables.Runnable extends Exception> action) {
return execute(() -> {
Futures.anyOf(Array.asList(ContinuableFuture.this, other)).get();
action.run();
return null;
}, other);
}
/**
* Run after either.
*
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterEither(final ContinuableFuture extends T> other,
final Throwables.Consumer super T, ? extends Exception> action) {
return execute(() -> {
final T result = Futures.anyOf(Array.asList(ContinuableFuture.this, other)).get();
action.accept(result);
return null;
}, other);
}
/**
* Run after either.
*
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterEither(final ContinuableFuture extends T> other,
final Throwables.BiConsumer super T, ? super Exception, ? extends Exception> action) {
return execute(() -> {
final Result result = Futures.anyOf(Array.asList(ContinuableFuture.this, other)).gett();
action.accept(result.orElseIfFailure(null), result.getException());
return null;
}, other);
}
/**
* Call after either.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterEither(final ContinuableFuture> other, final Callable action) {
return execute(() -> {
Futures.anyOf(Array.asList(ContinuableFuture.this, other)).get();
return action.call();
}, other);
}
/**
* Call after either.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterEither(final ContinuableFuture extends T> other,
final Throwables.Function super T, ? extends R, ? extends Exception> action) {
return execute(() -> {
final T result = Futures.anyOf(Array.asList(ContinuableFuture.this, other)).get();
return action.apply(result);
}, other);
}
/**
* Call after either.
*
* @param
* @param other
* @param action
* @return
*/
public ContinuableFuture callAfterEither(final ContinuableFuture extends T> other,
final Throwables.BiFunction super T, ? super Exception, ? extends R, ? extends Exception> action) {
return execute(() -> {
final Result result = Futures.anyOf(Array.asList(ContinuableFuture.this, other)).gett();
return action.apply(result.orElseIfFailure(null), result.getException());
}, other);
}
/**
* Run after either.
*
* @param other
* @param action
* @return
*/
public ContinuableFuture runAfterFirstSucceed(final ContinuableFuture> other, final Throwables.Runnable extends Exception> action) {
return execute(() -> {
final ObjIterator> iter = Futures.iteratte(ContinuableFuture.this, other);
final Result