From 59137afadf3d66d2e7aad56dd0d4634a8f66b0c6 Mon Sep 17 00:00:00 2001 From: Jerry Lee Date: Sat, 18 May 2024 21:52:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20implement=20`mostTupleOfSuccess`=20meth?= =?UTF-8?q?ods=20=F0=9F=9A=80=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/foldright/cffu/CffuFactory.java | 82 ++++++- .../cffu/CompletableFutureUtils.java | 202 ++++++++++-------- .../cffu/CompletableFutureUtilsTest.java | 64 ++++-- .../foldright/cffu/kotlin/CffuExtensions.kt | 21 +- .../kotlin/CompletableFutureExtensions.kt | 82 ++++++- 5 files changed, 327 insertions(+), 124 deletions(-) diff --git a/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java b/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java index 2f30491c..eaf69610 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CffuFactory.java @@ -301,7 +301,7 @@ public final Cffu[] toCffuArray(CompletionStage... stages) { // // - allOf / allOfFastFail // - allResultsOf / allResultsOfFastFail - // - allResultsOf / allResultsOfFastFail + // - mostResultsOfSuccess //////////////////////////////////////////////////////////////////////////////// /** @@ -423,7 +423,6 @@ public final Cffu> allResultsOfFastFail(CompletionStage * the given stages in the given time({@code timeout}), aka as many results as possible in the given time. *

* If the given stage is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is {@link Cffu#getSuccessNow(Object)}). * * @param timeout how long to wait in units of {@code unit} * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter @@ -431,7 +430,6 @@ public final Cffu> allResultsOfFastFail(CompletionStage * @param cfs the stages * @see Cffu#getSuccessNow(Object) */ - // TODO * @see CompletableFutureUtils#MGetSuccessNow(Object, CompletionStage[]) @Contract(pure = true) @SafeVarargs public final Cffu> mostResultsOfSuccess( @@ -495,6 +493,7 @@ public final Cffu anyOfSuccess(CompletionStage... cfs) { // // - allTupleOf // - allTupleOfFastFail + // - mostTupleOfSuccess //////////////////////////////////////////////////////////////////////////////// /** @@ -633,6 +632,83 @@ public Cffu> allTupleOfFastFail( return new0(CompletableFutureUtils.allTupleOfFastFail(cf1, cf2, cf3, cf4, cf5)); } + /** + * Returns a new Cffu with the most results in the same order of + * the given two stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new Cffu that is completed when the given two stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see Cffu#getSuccessNow(Object) + */ + @Contract(pure = true) + public Cffu> mostTupleOfSuccess( + long timeout, TimeUnit unit, CompletionStage cf1, CompletionStage cf2) { + return new0(CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2)); + } + + /** + * Returns a new Cffu with the most results in the same order of + * the given three stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new Cffu that is completed when the given three stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see Cffu#getSuccessNow(Object) + */ + @Contract(pure = true) + public Cffu> mostTupleOfSuccess( + long timeout, TimeUnit unit, + CompletionStage cf1, CompletionStage cf2, CompletionStage cf3) { + return new0(CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2, cf3)); + } + + /** + * Returns a new Cffu with the most results in the same order of + * the given four stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new Cffu that is completed when the given four stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see Cffu#getSuccessNow(Object) + */ + @Contract(pure = true) + public Cffu> mostTupleOfSuccess( + long timeout, TimeUnit unit, + CompletionStage cf1, CompletionStage cf2, + CompletionStage cf3, CompletionStage cf4) { + return new0(CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2, cf3, cf4)); + } + + /** + * Returns a new Cffu with the most results in the same order of + * the given five stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new Cffu that is completed when the given five stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see Cffu#getSuccessNow(Object) + */ + @Contract(pure = true) + public Cffu> mostTupleOfSuccess( + long timeout, TimeUnit unit, + CompletionStage cf1, CompletionStage cf2, CompletionStage cf3, + CompletionStage cf4, CompletionStage cf5) { + return new0(CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2, cf3, cf4, cf5)); + } + //////////////////////////////////////////////////////////////////////////////// //# Delay Execution, equivalent to same name static methods of CompletableFuture // 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 66885aaa..fc4ee004 100644 --- a/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java +++ b/cffu-core/src/main/java/io/foldright/cffu/CompletableFutureUtils.java @@ -190,7 +190,6 @@ public static CompletableFuture> allResultsOfFastFail(CompletionStag * the given stages in the given time({@code timeout}), aka as many results as possible in the given time. *

* If the given stage is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is {@link #getSuccessNow(CompletableFuture, Object)}). * * @param timeout how long to wait in units of {@code unit} * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter @@ -198,7 +197,6 @@ public static CompletableFuture> allResultsOfFastFail(CompletionStag * @param cfs the stages * @see #getSuccessNow(CompletableFuture, Object) */ - // * @see #MGetSuccessNow(Object, CompletionStage[]) @Contract(pure = true) @SafeVarargs public static CompletableFuture> mostResultsOfSuccess( @@ -208,14 +206,34 @@ public static CompletableFuture> mostResultsOfSuccess( if (cfs.length == 0) return CompletableFuture.completedFuture(arrayList()); if (cfs.length == 1) { + // defensive copy input cf in order to + // avoid writing it by `completeOnTimeout` and read its result(`getSuccessNow`) final CompletableFuture f = toCfCopy(cfs[0]); - return orTimeout(f, timeout, unit).handle((unused, ex) -> arrayList(getSuccessNow(f, valueIfNotSuccess))); + return orTimeout(f, timeout, unit) + .handle((unused, ex) -> arrayList(getSuccessNow(f, valueIfNotSuccess))); } - // MUST be Non-Minimal CF instances in order to read results, otherwise UnsupportedOperationException + // MUST be *Non-Minimal* CF instances in order to read results(`getSuccessNow`), + // otherwise UnsupportedOperationException final CompletableFuture[] cfArray = f_toNonMinCfArray(cfs); return orTimeout(CompletableFuture.allOf(cfArray), timeout, unit) - .handle((unused, ex) -> MGetSuccessNow(valueIfNotSuccess, cfArray)); + .handle((unused, ex) -> arrayList(MGetSuccessNow0(valueIfNotSuccess, cfArray))); + } + + /** + * Multi-Gets(MGet) the results in the same order of the given cfs, + * use the result value if the given stage is completed successfully, else use the given valueIfNotSuccess + * + * @param cfs MUST be *Non-Minimal* CF instances in order to read results(`getSuccessNow`), + * otherwise UnsupportedOperationException + */ + @SuppressWarnings("unchecked") + private static T[] MGetSuccessNow0(@Nullable Object valueIfNotSuccess, CompletableFuture... cfs) { + Object[] ret = new Object[cfs.length]; + for (int i = 0; i < cfs.length; i++) { + ret[i] = getSuccessNow(cfs[i], valueIfNotSuccess); + } + return (T[]) ret; } @SafeVarargs @@ -396,6 +414,7 @@ public static CompletableFuture anyOfSuccess(CompletionStage requireCfsAndEleNonNull(cfs); final int size = cfs.length; if (size == 0) return failedFuture(new NoCfsProvidedException()); + // defensive copy input cf to avoid writing it unexpectedly it by caller code if (size == 1) return toCfCopy(cfs[0]); // NOTE: fill ONE MORE element of successOrBeIncompleteCfs LATER @@ -412,7 +431,7 @@ public static CompletableFuture anyOfSuccess(CompletionStage } //////////////////////////////////////////////////////////////////////////////// - //# allTupleOf* methods + //# allTupleOf*/mostTupleOfSuccess methods //////////////////////////////////////////////////////////////////////////////// /** @@ -552,16 +571,14 @@ public static CompletableFuture> } private static CompletableFuture allTupleOf0(CompletionStage[] css, boolean fastFail) { - final int length = css.length; - final Object[] result = new Object[length]; + final Object[] result = new Object[css.length]; final CompletableFuture[] resultSetterCfs = createResultSetterCfs(css, result); final CompletableFuture resultSetter; if (fastFail) resultSetter = allOfFastFail(resultSetterCfs); else resultSetter = CompletableFuture.allOf(resultSetterCfs); - final CompletableFuture ret = resultSetter.thenApply(unused -> tupleOf0(result)); - return f_cast(ret); + return resultSetter.thenApply(unused -> tupleOf0(result)); } @SuppressWarnings("unchecked") @@ -575,6 +592,93 @@ private static T tupleOf0(Object... elements) { return (T) ret; } + /** + * Returns a new CompletableFuture with the most results in the same order of + * the given two stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new CompletableFuture that is completed when the given two stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see #getSuccessNow(CompletableFuture, Object) + */ + @Contract(pure = true) + public static CompletableFuture> mostTupleOfSuccess( + long timeout, TimeUnit unit, CompletionStage cf1, CompletionStage cf2) { + return mostTupleOfSuccess0(timeout, unit, requireCfsAndEleNonNull(cf1, cf2)); + } + + /** + * Returns a new CompletableFuture with the most results in the same order of + * the given three stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new CompletableFuture that is completed when the given three stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see #getSuccessNow(CompletableFuture, Object) + */ + @Contract(pure = true) + public static CompletableFuture> mostTupleOfSuccess( + long timeout, TimeUnit unit, + CompletionStage cf1, CompletionStage cf2, CompletionStage cf3) { + return mostTupleOfSuccess0(timeout, unit, requireCfsAndEleNonNull(cf1, cf2, cf3)); + } + + /** + * Returns a new CompletableFuture with the most results in the same order of + * the given four stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new CompletableFuture that is completed when the given four stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see #getSuccessNow(CompletableFuture, Object) + */ + @Contract(pure = true) + public static CompletableFuture> mostTupleOfSuccess( + long timeout, TimeUnit unit, + CompletionStage cf1, CompletionStage cf2, + CompletionStage cf3, CompletionStage cf4) { + return mostTupleOfSuccess0(timeout, unit, requireCfsAndEleNonNull(cf1, cf2, cf3, cf4)); + } + + /** + * Returns a new CompletableFuture with the most results in the same order of + * the given five stages in the given time({@code timeout}), aka as many results as possible in the given time. + *

+ * If the given stage is successful, its result is the completed value; Otherwise the value {@code null}. + * + * @param timeout how long to wait in units of {@code unit} + * @param unit a {@code TimeUnit} determining how to interpret the {@code timeout} parameter + * @return a new CompletableFuture that is completed when the given five stages complete + * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) + * @see #getSuccessNow(CompletableFuture, Object) + */ + @Contract(pure = true) + public static CompletableFuture> mostTupleOfSuccess( + long timeout, TimeUnit unit, + CompletionStage cf1, CompletionStage cf2, CompletionStage cf3, + CompletionStage cf4, CompletionStage cf5) { + return mostTupleOfSuccess0(timeout, unit, requireCfsAndEleNonNull(cf1, cf2, cf3, cf4, cf5)); + } + + private static CompletableFuture mostTupleOfSuccess0( + long timeout, TimeUnit unit, CompletionStage[] css) { + requireNonNull(unit, "unit is null"); + // MUST be *Non-Minimal* CF instances in order to read results(`getSuccessNow`), + // otherwise UnsupportedOperationException + final CompletableFuture[] cfArray = f_toNonMinCfArray(css); + return orTimeout(CompletableFuture.allOf(cfArray), timeout, unit) + .handle((unused, ex) -> tupleOf0(MGetSuccessNow0(null, cfArray))); + } + //////////////////////////////////////////////////////////////////////////////// //# `then both(binary input)` methods with fast-fail support: // @@ -1375,6 +1479,7 @@ C exceptionallyComposeAsync(C cf, Function T join(CompletableFuture cf, long timeout, TimeUnit unit) { if (cf.isDone()) return cf.join(); + // defensive copy input cf to avoid writing it by `orTimeout` return orTimeout(copy(cf), timeout, unit).join(); } @@ -1387,7 +1492,6 @@ public static T join(CompletableFuture cf, long timeout, TimeUnit unit) { * @param valueIfNotSuccess the value to return if not completed successfully * @return the result value, if completed successfully, else the given valueIfNotSuccess */ - // * @see #MGetSuccessNow(Object, CompletionStage[]) @Contract(pure = true) @Nullable public static T getSuccessNow(CompletableFuture cf, @Nullable T valueIfNotSuccess) { @@ -1511,82 +1615,6 @@ public static CffuState state(CompletableFuture cf) { } } - //# New enhanced multi-read(explicitly) methods - - /** - * Multi-Gets(MGet) the results in the same order of the given cfs, - * use the result value if the given stage is completed successfully, else use the given valueIfNotSuccess - * (aka the result extraction logic is {@link #getSuccessNow(CompletableFuture, Object)}). - * - * @param cfs the stages - * @see #mostResultsOfSuccess(long, TimeUnit, Object, CompletionStage[]) - * @see #getSuccessNow(CompletableFuture, Object) - */ - @Contract(pure = true) - @SafeVarargs - static List MGetSuccessNow(@Nullable T valueIfNotSuccess, CompletionStage... cfs) { - return arrayList(MGet0(cf -> getSuccessNow(cf, valueIfNotSuccess), cfs)); - } - - @SafeVarargs - @SuppressWarnings("unchecked") - private static T[] MGet0(Function, ? extends T> resultGetter, - CompletionStage... cfs) { - final CompletableFuture[] cfArray = f_toCfArray(cfs); - Object[] ret = new Object[cfs.length]; - for (int i = 0; i < cfArray.length; i++) { - CompletableFuture cf = cfArray[i]; - ret[i] = resultGetter.apply(cf); - } - return (T[]) ret; - } - - /** - * Multi-Gets(MGet) the result value in the same order of the given cfs, - * use the result value if the cf is completed successfully, else use the value {@code null} - * (aka the result extraction logic is {@code getSuccessNow(cf, null)}). - */ - static Tuple2 tupleGetSuccessNow( - CompletionStage cf1, CompletionStage cf2) { - return tupleGet0(requireCfsAndEleNonNull(cf1, cf2)); - } - - /** - * Multi-Gets(MGet) the result value in the same order of the given cfs, - * use the result value if the cf is completed successfully, else use the value {@code null} - * (aka the result extraction logic is {@code getSuccessNow(cf, null)}). - */ - static Tuple3 tupleGetSuccessNow( - CompletionStage cf1, CompletionStage cf2, CompletionStage cf3) { - return tupleGet0(requireCfsAndEleNonNull(cf1, cf2, cf3)); - } - - /** - * Multi-Gets(MGet) the result value in the same order of the given cfs, - * use the result value if the cf is completed successfully, else use the value {@code null} - * (aka the result extraction logic is {@code getSuccessNow(cf, null)}). - */ - static Tuple4 tupleGetSuccessNow( - CompletionStage cf1, CompletionStage cf2, - CompletionStage cf3, CompletionStage cf4) { - return tupleGet0(requireCfsAndEleNonNull(cf1, cf2, cf3, cf4)); - } - - /** - * Multi-Gets(MGet) the result value in the same order of the given cfs, - * use the result value if the cf is completed successfully, else the value {@code null} - * (aka the result extraction logic is {@code getSuccessNow(cf, null)}). - */ - static Tuple5 tupleGetSuccessNow( - CompletionStage cf1, CompletionStage cf2, CompletionStage cf3, - CompletionStage cf4, CompletionStage cf5) { - return tupleGet0(requireCfsAndEleNonNull(cf1, cf2, cf3, cf4, cf5)); - } - - private static T tupleGet0(CompletionStage... css) { - return tupleOf0(MGet0(cf -> getSuccessNow(cf, null), css)); - } - //# Write methods of CompletableFuture /** diff --git a/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java b/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java index 5f884be3..67cd2b77 100644 --- a/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java +++ b/cffu-core/src/test/java/io/foldright/cffu/CompletableFutureUtilsTest.java @@ -323,11 +323,23 @@ void test_mostOf() throws Exception { final CompletableFuture cancelled = createCancelledFuture(); final CompletableFuture incomplete = createIncompleteFuture(); + // 0 input cf assertEquals(0, mostResultsOfSuccess(10, TimeUnit.MILLISECONDS, null).get().size()); + // 1 input cf assertEquals(Collections.singletonList(n), mostResultsOfSuccess( 10, TimeUnit.MILLISECONDS, null, completed).get()); + assertEquals(Collections.singletonList(n), mostResultsOfSuccess( + 10, TimeUnit.MILLISECONDS, anotherN, completed).get()); + + assertEquals(Collections.singletonList(anotherN), mostResultsOfSuccess( + 10, TimeUnit.MILLISECONDS, anotherN, failed).get()); + assertEquals(Collections.singletonList(anotherN), mostResultsOfSuccess( + 10, TimeUnit.MILLISECONDS, anotherN, cancelled).get()); + assertEquals(Collections.singletonList(anotherN), mostResultsOfSuccess( + 10, TimeUnit.MILLISECONDS, anotherN, incomplete).get()); + // more input cf assertEquals(Arrays.asList(n, null, null, null), mostResultsOfSuccess( 10, TimeUnit.MILLISECONDS, null, completed, failed, cancelled, incomplete ).get()); @@ -689,6 +701,40 @@ void test_allTupleOf_NotFastFail() throws Exception { } } + @Test + void test_mostTupleOfSuccess() throws Exception { + final CompletableFuture completed = completedFuture(n); + final CompletableFuture anotherCompleted = completedFuture(s); + final CompletableFuture failed = failedFuture(rte); + final CompletableFuture cancelled = createCancelledFuture(); + final CompletableFuture incomplete = createIncompleteFuture(); + + assertEquals(Tuple2.of(n, s), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, completed, anotherCompleted + ).get()); + assertEquals(Tuple2.of(n, null), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, completed, failed + ).get()); + + assertEquals(Tuple3.of(n, s, null), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, completed, anotherCompleted, cancelled + ).get()); + assertEquals(Tuple3.of(null, null, s), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, incomplete, failed, anotherCompleted + ).get()); + + assertEquals(Tuple4.of(n, s, null, null), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, completed, anotherCompleted, cancelled, incomplete + ).get()); + assertEquals(Tuple4.of(null, null, null, null), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, incomplete, failed, cancelled, incomplete + ).get()); + + assertEquals(Tuple5.of(null, n, s, null, null), mostTupleOfSuccess( + 10, TimeUnit.MILLISECONDS, cancelled, completed, anotherCompleted, incomplete, failed + ).get()); + } + //////////////////////////////////////////////////////////////////////////////// //# both methods //////////////////////////////////////////////////////////////////////////////// @@ -1012,24 +1058,6 @@ void test_read() { assertEquals(n, join(later, 3, TimeUnit.SECONDS)); } - @Test - void test_gets() { - final CompletableFuture completed = completedFuture(n); - final CompletableFuture failed = failedFuture(rte); - final CompletableFuture cancelled = createCancelledFuture(); - final CompletableFuture incomplete = createIncompleteFuture(); - - assertEquals(Arrays.asList(n, anotherN, anotherN, anotherN), - MGetSuccessNow(anotherN, completed, incomplete, cancelled, failed)); - - assertEquals(Tuple2.of(n, null), tupleGetSuccessNow(completed, failed)); - assertEquals(Tuple3.of(null, n, null), tupleGetSuccessNow(failed, completed, cancelled)); - assertEquals(Tuple4.of(null, n, null, anotherN), - tupleGetSuccessNow(failed, completed, cancelled, completedFuture(anotherN))); - assertEquals(Tuple5.of(null, n, null, anotherN, null), - tupleGetSuccessNow(failed, completed, cancelled, completedFuture(anotherN), failed)); - } - @Test void test_write() throws Exception { assertEquals(n, completeAsync(createIncompleteFuture(), () -> n).get()); diff --git a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt index 12aa52fb..71dc93d6 100644 --- a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt +++ b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CffuExtensions.kt @@ -395,16 +395,14 @@ fun Array>.allOfFastFailCffu(cffuFactory: CffuFactory): C * the given Cffus in the given time(`timeout`), aka as many results as possible in the given time. * * If the given Cffu is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is [Cffu.getSuccessNow]). - * - * The result extraction logic can be customized using another overloaded [mostResultsOfSuccessCffu] method. * * @param timeout how long to wait in units of `unit` * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter * @param valueIfNotSuccess the value to return if not completed successfully + * @see CffuFactory.mostResultsOfSuccess + * @see CffuFactory.mostTupleOfSuccess * @see Cffu.getSuccessNow */ -// * @see CompletableFutureUtils.MGetSuccessNow fun Collection>.mostResultsOfSuccessCffu( timeout: Long, unit: TimeUnit, valueIfNotSuccess: T, cffuFactory: CffuFactory = ABSENT ): Cffu> { @@ -418,19 +416,19 @@ fun Collection>.mostResultsOfSuccessCffu( * the given Cffus in the given time(`timeout`), aka as many results as possible in the given time. * * If the given Cffu is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is [Cffu.getSuccessNow]). * * @param timeout how long to wait in units of `unit` * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter * @param valueIfNotSuccess the value to return if not completed successfully + * @see CffuFactory.mostResultsOfSuccess + * @see CffuFactory.mostTupleOfSuccess * @see Cffu.getSuccessNow */ -// * @see CompletableFutureUtils.MGetSuccessNow fun Array>.mostResultsOfSuccessCffu( timeout: Long, unit: TimeUnit, valueIfNotSuccess: T, cffuFactory: CffuFactory = ABSENT ): Cffu> { val factory: CffuFactory = if (cffuFactory !== ABSENT) cffuFactory - else firstOrNull()?.cffuFactory() ?: throw IllegalArgumentException(ERROR_MSG_FOR_COLL) + else firstOrNull()?.cffuFactory() ?: throw IllegalArgumentException(ERROR_MSG_FOR_ARRAY) return factory.mostResultsOfSuccess(timeout, unit, valueIfNotSuccess, *this) } @@ -439,16 +437,14 @@ fun Array>.mostResultsOfSuccessCffu( * the given stages in the given time(`timeout`), aka as many results as possible in the given time. * * If the given stage is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is [Cffu.getSuccessNow]). - * - * The result extraction logic can be customized using another overloaded [mostResultsOfSuccessCffu] method. * * @param timeout how long to wait in units of `unit` * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter * @param valueIfNotSuccess the value to return if not completed successfully + * @see CffuFactory.mostResultsOfSuccess + * @see CffuFactory.mostTupleOfSuccess * @see Cffu.getSuccessNow */ -// * @see CompletableFutureUtils.MGetSuccessNow @JvmName("mostResultsOfSuccessCffuCs") fun Collection>.mostResultsOfSuccessCffu( timeout: Long, unit: TimeUnit, valueIfNotSuccess: T, cffuFactory: CffuFactory @@ -465,9 +461,10 @@ fun Collection>.mostResultsOfSuccessCffu( * @param timeout how long to wait in units of `unit` * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter * @param valueIfNotSuccess the value to return if not completed successfully + * @see CffuFactory.mostResultsOfSuccess + * @see CffuFactory.mostTupleOfSuccess * @see Cffu.getSuccessNow */ -// * @see CompletableFutureUtils.MGetSuccessNow fun Array>.mostResultsOfSuccessCffu( timeout: Long, unit: TimeUnit, valueIfNotSuccess: T, cffuFactory: CffuFactory ): Cffu> = diff --git a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt index f4b33ef6..70ab2c13 100644 --- a/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt +++ b/cffu-kotlin/src/main/java/io/foldright/cffu/kotlin/CompletableFutureExtensions.kt @@ -212,14 +212,14 @@ fun Array>.allResultsOfFastFailCompletableFuture( * the given stages in the given time(`timeout`), aka as many results as possible in the given time. * * If the given stage is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is [getSuccessNow]). * * @param timeout how long to wait in units of `unit` * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter * @param valueIfNotSuccess the value to return if not completed successfully + * @see CompletableFutureUtils.mostResultsOfSuccess + * @see CompletableFutureUtils.mostTupleOfSuccess * @see getSuccessNow */ -// * @see CompletableFutureUtils.MGetSuccessNow fun Collection>.mostResultsOfSuccessCompletableFuture( timeout: Long, unit: TimeUnit, valueIfNotSuccess: T ): CompletableFuture> = @@ -230,14 +230,14 @@ fun Collection>.mostResultsOfSuccessCompletableFuture * the given stages in the given time(`timeout`), aka as many results as possible in the given time. * * If the given stage is successful, its result is the completed value; Otherwise the given valueIfNotSuccess. - * (aka the result extraction logic is [getSuccessNow]). * * @param timeout how long to wait in units of `unit` * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter * @param valueIfNotSuccess the value to return if not completed successfully + * @see CompletableFutureUtils.mostResultsOfSuccess + * @see CompletableFutureUtils.mostTupleOfSuccess * @see getSuccessNow */ -// * @see CompletableFutureUtils.MGetSuccessNow fun Array>.mostResultsOfSuccessCompletableFuture( timeout: Long, unit: TimeUnit, valueIfNotSuccess: T ): CompletableFuture> = @@ -486,6 +486,7 @@ fun CompletionStage.thenCombineFastFailAsync( // // - allTupleOf // - allTupleOfFastFail +// - mostTupleOfSuccess //////////////////////////////////////// /** @@ -618,6 +619,79 @@ fun CompletionStage.allTupleOfFastFail( ): CompletableFuture> = CompletableFutureUtils.allTupleOfFastFail(this, cf2, cf3, cf4, cf5) +/** + * Returns a new CompletableFuture with the most results in the **same order** of + * the given two stages in the given time(`timeout`), aka as many results as possible in the given time. + * + * If the given stage is successful, its result is the completed value; Otherwise the value `null`. + * + * @param timeout how long to wait in units of `unit` + * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter + * @return a new CompletableFuture that is completed when the given two stages complete + * @see mostResultsOfSuccessCompletableFuture + * @see getSuccessNow + */ +fun mostTupleOfSuccess( + timeout: Long, unit: TimeUnit, cf1: CompletionStage, cf2: CompletionStage +): CompletableFuture> = + CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2) + +/** + * Returns a new CompletableFuture with the most results in the **same order** of + * the given three stages in the given time(`timeout`), aka as many results as possible in the given time. + * + * If the given stage is successful, its result is the completed value; Otherwise the value `null`. + * + * @param timeout how long to wait in units of `unit` + * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter + * @return a new CompletableFuture that is completed when the given three stages complete + * @see mostResultsOfSuccessCompletableFuture + * @see getSuccessNow + */ +fun mostTupleOfSuccess( + timeout: Long, unit: TimeUnit, + cf1: CompletionStage, cf2: CompletionStage, cf3: CompletionStage +): CompletableFuture> = + CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2, cf3) + +/** + * Returns a new CompletableFuture with the most results in the **same order** of + * the given four stages in the given time(`timeout`), aka as many results as possible in the given time. + * + * If the given stage is successful, its result is the completed value; Otherwise the value `null`. + * + * @param timeout how long to wait in units of `unit` + * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter + * @return a new CompletableFuture that is completed when the given four stages complete + * @see mostResultsOfSuccessCompletableFuture + * @see getSuccessNow + */ +fun mostTupleOfSuccess( + timeout: Long, unit: TimeUnit, + cf1: CompletionStage, cf2: CompletionStage, + cf3: CompletionStage, cf4: CompletionStage +): CompletableFuture> = + CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2, cf3, cf4) + +/** + * Returns a new CompletableFuture with the most results in the **same order** of + * the given five stages in the given time(`timeout`), aka as many results as possible in the given time. + * + * If the given stage is successful, its result is the completed value; Otherwise the value `null`. + * + * @param timeout how long to wait in units of `unit` + * @param unit a `TimeUnit` determining how to interpret the `timeout` parameter + * @return a new CompletableFuture that is completed when the given five stages complete + * @see mostResultsOfSuccessCompletableFuture + * @see getSuccessNow + */ +fun mostTupleOfSuccess( + timeout: Long, unit: TimeUnit, + cf1: CompletionStage, cf2: CompletionStage, cf3: CompletionStage, + cf4: CompletionStage, cf5: CompletionStage +): CompletableFuture> = + CompletableFutureUtils.mostTupleOfSuccess(timeout, unit, cf1, cf2, cf3, cf4, cf5) + //////////////////////////////////////////////////////////////////////////////// //# `then either(binary input)` methods with either(any)-success support: //