From a3377c97b7335e5f391405df9b2db7034eee64a4 Mon Sep 17 00:00:00 2001 From: Jerry Lee Date: Sat, 14 Dec 2024 18:49:52 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20move=20`completeCf`=20method=20to?= =?UTF-8?q?=20`LLCF`=20class=20=F0=9F=94=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cffu/CompletableFutureUtils.java | 9 ++---- .../src/main/java/io/foldright/cffu/LLCF.java | 19 ++++++++++-- .../test/java/io/foldright/cffu/LLCFTest.kt | 30 +++++++++++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 cffu-core/src/test/java/io/foldright/cffu/LLCFTest.kt diff --git a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java index 5da48060..9f4806ff 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -3061,18 +3061,13 @@ private static > C hopExecutorIfAtCfDelayerThread CompletableFuture ret = newIncompleteFuture(cf); peek0(cf, (v, ex) -> { - if (!atCfDelayerThread()) completeCf(ret, v, ex); - else screenExecutor(executor).execute(() -> completeCf(ret, v, ex)); + if (!atCfDelayerThread()) completeCf0(ret, v, ex); + else screenExecutor(executor).execute(() -> completeCf0(ret, v, ex)); }, "handle of executor hop"); return (C) ret; } - private static void completeCf(CompletableFuture cf, Object value, @Nullable Throwable ex) { - if (ex == null) cf.complete(value); - else cf.completeExceptionally(ex); - } - // endregion //////////////////////////////////////////////////////////// // region## Advanced Methods of CompletionStage(compose* and handle-like methods) diff --git a/cffu-core/src/main/java/io/foldright/cffu/LLCF.java b/cffu-core/src/main/java/io/foldright/cffu/LLCF.java index e8f7d9d8..7cffff9a 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/LLCF.java +++ b/cffu-core/src/main/java/io/foldright/cffu/LLCF.java @@ -1,5 +1,6 @@ package io.foldright.cffu; +import edu.umd.cs.findbugs.annotations.Nullable; import org.jetbrains.annotations.Contract; import java.util.ArrayList; @@ -127,6 +128,14 @@ static CompletableFuture toNonMinCfCopy0(CompletionStage s) return isMinStageCf(f) ? f.toCompletableFuture() : IS_JAVA9_PLUS ? f.copy() : f.thenApply(x -> x); } + public static boolean isMinStageCf(CompletableFuture cf) { + return cf.getClass().equals(MIN_STAGE_CLASS); + } + + //////////////////////////////////////////////////////////////////////////////// + // region# Low level operations of CompletableFuture + //////////////////////////////////////////////////////////////////////////////// + /** * Peeks the result by executing the given action when the given stage completes, returns the given stage. * The uncaught exceptions thrown by the action are reported. @@ -167,8 +176,14 @@ C peekAsync0(C cfThis, BiConsumer action, String w return cfThis; } - public static boolean isMinStageCf(CompletableFuture cf) { - return cf.getClass().equals(MIN_STAGE_CLASS); + /** + * Completes the given CompletableFuture with the exception(if non-null), otherwise with the value. + * In general, you should NEVER use this method in application codes, use {@link CompletableFuture#complete(Object)} + * or {@link CompletableFuture#completeExceptionally(Throwable)} instead. + */ + static boolean completeCf0(CompletableFuture cf, T value, @Nullable Throwable ex) { + if (ex == null) return cf.complete(value); + else return cf.completeExceptionally(ex); } // endregion diff --git a/cffu-core/src/test/java/io/foldright/cffu/LLCFTest.kt b/cffu-core/src/test/java/io/foldright/cffu/LLCFTest.kt new file mode 100644 index 00000000..2891e624 --- /dev/null +++ b/cffu-core/src/test/java/io/foldright/cffu/LLCFTest.kt @@ -0,0 +1,30 @@ +package io.foldright.cffu + +import io.foldright.test_utils.n +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.booleans.shouldBeFalse +import io.kotest.matchers.booleans.shouldBeTrue +import io.kotest.matchers.future.shouldBeCompleted +import io.kotest.matchers.future.shouldCompleteExceptionallyWith +import io.kotest.matchers.ints.shouldBeExactly +import java.util.concurrent.CompletableFuture + +class LLCFTest : FunSpec({ + test("completeCf0 - success") { + val cf = CompletableFuture() + LLCF.completeCf0(cf, n, null).shouldBeTrue() + cf.shouldBeCompleted() + cf.get() shouldBeExactly n + + LLCF.completeCf0(cf, n, null).shouldBeFalse() + } + + test("completeCf0 - exceptionally") { + val cf = CompletableFuture() + val ex = RuntimeException("foo") + LLCF.completeCf0(cf, n, ex).shouldBeTrue() + cf.shouldCompleteExceptionallyWith(ex) + + LLCF.completeCf0(cf, n, ex).shouldBeFalse() + } +})