Skip to content

Commit

Permalink
feat: add getSuccessNow methods ☘️
Browse files Browse the repository at this point in the history
  • Loading branch information
oldratlee committed May 18, 2024
1 parent 6906bc5 commit c6449db
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 4 deletions.
33 changes: 33 additions & 0 deletions cffu-core/src/main/java/io/foldright/cffu/Cffu.java
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,7 @@ public Cffu<T> peekAsync(BiConsumer<? super T, ? super Throwable> action, Execut
// - join() // BLOCKING!
// - join(timeout, unit) // BLOCKING!
// - getNow(T valueIfAbsent)
// - getSuccessNow(T valueIfAbsent)
// - resultNow()
// - exceptionNow()
//
Expand All @@ -1508,6 +1509,7 @@ public Cffu<T> peekAsync(BiConsumer<? super T, ? super Throwable> action, Execut
* @see #join()
* @see #join(long, TimeUnit)
* @see #getNow(Object)
* @see #getSuccessNow(Object)
* @see #resultNow()
* @see #get(long, TimeUnit)
*/
Expand All @@ -1532,6 +1534,7 @@ public T get() throws InterruptedException, ExecutionException {
* @throws TimeoutException if the wait timed out
* @see #join(long, TimeUnit)
* @see #getNow(Object)
* @see #getSuccessNow(Object)
* @see #resultNow()
* @see #join()
* @see #get()
Expand All @@ -1557,6 +1560,7 @@ public T get(long timeout, TimeUnit unit) throws InterruptedException, Execution
* or a completion computation threw an exception
* @see #join(long, TimeUnit)
* @see #getNow(Object)
* @see #getSuccessNow(Object)
* @see #resultNow()
* @see #get(long, TimeUnit)
* @see #get()
Expand Down Expand Up @@ -1598,6 +1602,7 @@ public T join() {
* or the wait timed out(with the {@code TimeoutException} as its cause)
* @see #join()
* @see #getNow(Object)
* @see #getSuccessNow(Object)
* @see #resultNow()
* @see #get(long, TimeUnit)
* @see #get()
Expand All @@ -1619,6 +1624,7 @@ public T join(long timeout, TimeUnit unit) {
* @throws CancellationException if the computation was cancelled
* @throws CompletionException if this future completed exceptionally
* or a completion computation threw an exception
* @see #getSuccessNow(Object)
* @see #resultNow()
* @see #join(long, TimeUnit)
* @see #join()
Expand All @@ -1632,6 +1638,27 @@ public T getNow(T valueIfAbsent) {
return cf.getNow(valueIfAbsent);
}

/**
* Returns the result value if completed successfully, else returns the given valueIfNotSuccess.
* <p>
* This method will not throw exceptions
* (CancellationException/CompletionException/ExecutionException/IllegalStateException/...).
*
* @param valueIfNotSuccess the value to return if not completed successfully
* @return the result value, if completed successfully, else the given valueIfNotSuccess
* @see #getNow(Object)
* @see #resultNow()
* @see #join(long, TimeUnit)
* @see #join()
* @see #get(long, TimeUnit)
* @see #get()
*/
@Contract(pure = true)
@Nullable
public T getSuccessNow(@Nullable T valueIfNotSuccess) {
return CompletableFutureUtils.getSuccessNow(cf, valueIfNotSuccess);
}

/**
* Returns the computed result, without waiting.
* <p>
Expand All @@ -1645,7 +1672,11 @@ public T getNow(T valueIfAbsent) {
* .toList();
* }</pre>
*
* @return the computed result
* @throws IllegalStateException if the task has not completed or the task did not complete with a result
* @see #getNow(Object)
* @see #getSuccessNow(Object)
* @see #exceptionNow()
*/
@Contract(pure = true)
@Nullable
Expand All @@ -1664,6 +1695,8 @@ public T resultNow() {
* @throws IllegalStateException if the task has not completed, the task completed normally,
* or the task was cancelled
* @see #resultNow()
* @see #getNow(Object)
* @see #getSuccessNow(Object)
*/
@Contract(pure = true)
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,22 @@ public static <T> T join(CompletableFuture<T> cf, long timeout, TimeUnit unit) {
return orTimeout(copy(cf), timeout, unit).join();
}

/**
* Returns the result value if the given stage is completed successfully, else returns the given valueIfNotSuccess.
* <p>
* This method will not throw exceptions
* (CancellationException/CompletionException/ExecutionException/IllegalStateException/...).
*
* @param valueIfNotSuccess the value to return if not completed successfully
* @return the result value, if completed successfully, else the given valueIfNotSuccess
*/
@Contract(pure = true)
@Nullable
public static <T> T getSuccessNow(CompletionStage<? extends T> cf, @Nullable T valueIfNotSuccess) {
final CompletableFuture<T> f = toCf(cf);
return f.isDone() && !f.isCompletedExceptionally() ? f.join() : valueIfNotSuccess;
}

/**
* Returns the computed result, without waiting.
* <p>
Expand Down
17 changes: 17 additions & 0 deletions cffu-core/src/test/java/io/foldright/cffu/CffuTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,23 @@ void test_cffuJoin() {
assertEquals(42, cffu.join(3, TimeUnit.SECONDS));
}

@Test
void test_getSuccessNow() {
final Consumer<Cffu<Integer>> check = (cf) -> {
assertNull(cf.getSuccessNow(null));
assertEquals(42, cf.getSuccessNow(42));
};

Cffu<Integer> incomplete = cffuFactory.newIncompleteCffu();
check.accept(incomplete);

Cffu<Integer> failed = cffuFactory.failedFuture(rte);
check.accept(failed);

incomplete.cancel(false);
check.accept(incomplete);
}

@Test
void test_cffuState() {
Cffu<Object> incomplete = cffuFactory.newIncompleteCffu();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.JRE;

import java.util.Arrays;
import java.util.Collections;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;

import static io.foldright.cffu.CompletableFutureUtils.*;
import static io.foldright.test_utils.TestUtils.*;
Expand Down Expand Up @@ -890,6 +887,8 @@ void test_read() {
final CompletableFuture<Integer> completed = completedFuture(n);

assertEquals(n, join(completed, 1, TimeUnit.MILLISECONDS));
assertEquals(n, getSuccessNow(completed, anotherN));
assertEquals(n, getSuccessNow(completed, null));
assertEquals(n, resultNow(completed));
try {
exceptionNow(completed);
Expand All @@ -909,6 +908,8 @@ void test_read() {
} catch (CompletionException expected) {
assertSame(rte, expected.getCause());
}
assertEquals(anotherN, getSuccessNow(failed, anotherN));
assertNull(getSuccessNow(failed, null));
try {
resultNow(failed);
fail();
Expand Down Expand Up @@ -945,6 +946,8 @@ void test_read() {
} catch (CompletionException expected) {
assertInstanceOf(TimeoutException.class, expected.getCause());
}
assertEquals(anotherN, getSuccessNow(incomplete, anotherN));
assertNull(getSuccessNow(incomplete, null));
try {
resultNow(incomplete);
fail();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -963,6 +963,19 @@ fun <T> CompletableFuture<T>.exceptionallyComposeAsync(
fun <T> CompletableFuture<T>.join(timeout: Long, unit: TimeUnit): T =
CompletableFutureUtils.join(this, timeout, unit) as T

/**
* Returns the result value if completed successfully, else returns the given valueIfNotSuccess.
*
* This method will not throw exceptions
* (CancellationException/CompletionException/ExecutionException/IllegalStateException/...).
*
* @param valueIfNotSuccess the value to return if not completed successfully
* @return the result value, if completed successfully, else the given valueIfNotSuccess
*/
@Suppress("UNCHECKED_CAST")
fun <T> CompletionStage<T>.getSuccessNow(valueIfNotSuccess: T): T =
CompletableFutureUtils.getSuccessNow(this, valueIfNotSuccess) as T

/**
* Returns the computed result, without waiting.
*
Expand All @@ -977,7 +990,7 @@ fun <T> CompletableFuture<T>.join(timeout: Long, unit: TimeUnit): T =
* ```
*/
@Suppress("UNCHECKED_CAST")
fun <T> CompletableFuture<out T>.resultNow(): T =
fun <T> CompletableFuture<T>.resultNow(): T =
CompletableFutureUtils.resultNow(this) as T

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ class CompletableFutureExtensionsTest : FunSpec({
val ff = CompletableFutureUtils.failedFuture<Int>(rte)

cf.join(1, TimeUnit.MILLISECONDS) shouldBe n
cf.getSuccessNow(null) shouldBe n
cf.resultNow() shouldBe n
ff.exceptionNow() shouldBeSameInstanceAs rte

Expand Down

0 comments on commit c6449db

Please sign in to comment.