diff --git a/cffu-core/src/main/java/io/foldright/cffu/ListenableFutureUtils.java b/cffu-core/src/main/java/io/foldright/cffu/ListenableFutureUtils.java index 0d925713..fd2c1445 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/ListenableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/ListenableFutureUtils.java @@ -30,24 +30,31 @@ public class ListenableFutureUtils { * Callback from ListenableFuture is executed using the given executor, * use {@link MoreExecutors#directExecutor()} if you need skip executor switch. *

- * Cancelling the result {@link CompletableFuture} will also cancel inner {@link ListenableFuture}. - * Use param {@code mayInterruptIfRunning} to control whether to interrupt the thread of {@link ListenableFuture}. + * Cancelling({@link Future#cancel(boolean)}) the returned CompletableFuture + * will also cancel underlying ListenableFuture. *

- * Note: CompletionException caused by this CancellationException is also considered cancellation. + * Use param {@code interruptLfWhenCancellationException} to control whether to cancel ListenableFuture with + * interruption when CancellationException occurred (including CompletionException/ExecutionException with + * CancellationException cause, more info see {@link CompletableFutureUtils#unwrapCfException(Throwable)}). *

- * We encourage you to avoid using direct write methods in {@link CompletableFuture} so that the underlying - * {@link ListenableFuture} can benefit from cancel propagation. + * It's recommended to avoid using direct write methods(e.g. {@link CompletableFuture#complete(Object)}, + * {@link CompletableFuture#completeExceptionally(Throwable)}) of the returned CompletableFuture: + *

* - * @param lf the wrapped ListenableFuture - * @param executor the executor - * @param mayInterruptIfRunning {@code true} if the thread of {@link ListenableFuture} should be interrupted when - * {@link CompletableFuture} canceled (if the thread is known to the implementation). - * @return the completable future + * @param lf the underlying ListenableFuture + * @param executor the executor to use for ListenableFuture callback execution + * @param interruptLfWhenCancellationException whether to cancel ListenableFuture with interruption when CancellationException occurred + * @return the CompletableFuture adapter * @see CompletableFuture#cancel(boolean) */ @Contract(pure = true) - public static CompletableFuture toCompletableFuture(ListenableFuture lf, Executor executor, boolean mayInterruptIfRunning) { + public static CompletableFuture toCompletableFuture( + ListenableFuture lf, Executor executor, boolean interruptLfWhenCancellationException) { requireNonNull(lf, "listenableFuture is null"); + requireNonNull(executor, "executor is null"); CompletableFuture ret = new CompletableFuture() { @Override @@ -68,7 +75,7 @@ public String toString() { CompletableFutureUtils.peek(ret, (v, ex) -> { ex = CompletableFutureUtils.unwrapCfException(ex); if (ex instanceof CancellationException) { - lf.cancel(mayInterruptIfRunning); + lf.cancel(interruptLfWhenCancellationException); } }); @@ -92,8 +99,9 @@ public void onFailure(Throwable ex) { * Callback from ListenableFuture is executed using cffuFactory's default executor. */ @Contract(pure = true) - public static Cffu toCffu(ListenableFuture lf, CffuFactory cffuFactory, boolean mayInterruptIfRunning) { - return cffuFactory.toCffu(toCompletableFuture(lf, cffuFactory.defaultExecutor(), mayInterruptIfRunning)); + public static Cffu toCffu( + ListenableFuture lf, CffuFactory cffuFactory, boolean interruptLfWhenCancellationException) { + return cffuFactory.toCffu(toCompletableFuture(lf, cffuFactory.defaultExecutor(), interruptLfWhenCancellationException)); } /**