From 4d01a8a418eb83126ebb24076a72ccde2a979ae0 Mon Sep 17 00:00:00 2001 From: WhatCats Date: Fri, 10 Jan 2025 21:15:52 +0100 Subject: [PATCH] cleanup combine methods --- .../futur/joiner/CompletionJoiner.java | 4 +- .../futur/joiner/MappedResultJoiner.java | 4 +- .../tommyjs/futur/joiner/PromiseJoiner.java | 52 +- .../tommyjs/futur/joiner/ResultJoiner.java | 4 +- .../dev/tommyjs/futur/joiner/VoidJoiner.java | 4 +- .../futur/promise/AbstractPromiseFactory.java | 58 +- .../tommyjs/futur/promise/PromiseFactory.java | 569 ++++++++---------- .../java/dev/tommyjs/futur/PromiseTests.java | 12 + .../java/dev/tommyjs/futur/lazy/Promises.java | 549 ++++++++--------- 9 files changed, 578 insertions(+), 678 deletions(-) diff --git a/futur-api/src/main/java/dev/tommyjs/futur/joiner/CompletionJoiner.java b/futur-api/src/main/java/dev/tommyjs/futur/joiner/CompletionJoiner.java index 8284805..82f9539 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/joiner/CompletionJoiner.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/joiner/CompletionJoiner.java @@ -16,11 +16,11 @@ public class CompletionJoiner extends PromiseJoiner, Void, Void, List public CompletionJoiner( @NotNull PromiseFactory factory, @NotNull Iterator> promises, - int expectedSize, boolean link + int expectedSize ) { super(factory); results = new ConcurrentResultArray<>(expectedSize); - join(promises, link); + join(promises); } @Override diff --git a/futur-api/src/main/java/dev/tommyjs/futur/joiner/MappedResultJoiner.java b/futur-api/src/main/java/dev/tommyjs/futur/joiner/MappedResultJoiner.java index 4fdcd65..ee64b0e 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/joiner/MappedResultJoiner.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/joiner/MappedResultJoiner.java @@ -15,11 +15,11 @@ public class MappedResultJoiner extends PromiseJoiner>> promises, - int expectedSize, boolean link + int expectedSize ) { super(factory); this.results = new ConcurrentResultArray<>(expectedSize); - join(promises, link); + join(promises); } @Override diff --git a/futur-api/src/main/java/dev/tommyjs/futur/joiner/PromiseJoiner.java b/futur-api/src/main/java/dev/tommyjs/futur/joiner/PromiseJoiner.java index 222bc27..56b465f 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/joiner/PromiseJoiner.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/joiner/PromiseJoiner.java @@ -10,49 +10,51 @@ import org.jetbrains.annotations.NotNull; import java.util.Iterator; import java.util.concurrent.atomic.AtomicInteger; -public abstract class PromiseJoiner { +public abstract class PromiseJoiner { - private final CompletablePromise joined; + private final CompletablePromise joined; protected PromiseJoiner(@NotNull PromiseFactory factory) { this.joined = factory.unresolved(); } - protected abstract K getChildKey(V value); + protected abstract Key getChildKey(T value); - protected abstract @NotNull Promise getChildPromise(V value); + protected abstract @NotNull Promise getChildPromise(T value); - protected abstract void onChildComplete(int index, K key, @NotNull PromiseCompletion completion); + protected abstract void onChildComplete(int index, Key key, @NotNull PromiseCompletion completion); - protected abstract R getResult(); + protected abstract Result getResult(); - protected void join(@NotNull Iterator promises, boolean link) { + protected void join(@NotNull Iterator promises) { AtomicInteger count = new AtomicInteger(); int i = 0; do { - V value = promises.next(); - Promise p = getChildPromise(value); + if (joined.isCompleted()) { + promises.forEachRemaining(v -> getChildPromise(v).cancel()); + return; + } - if (link) { + T value = promises.next(); + Promise p = getChildPromise(value); + if (!p.isCompleted()) { PromiseUtil.cancelOnComplete(joined, p); } - if (!joined.isCompleted()) { - count.incrementAndGet(); - K key = getChildKey(value); - int index = i++; + count.incrementAndGet(); + Key key = getChildKey(value); + int index = i++; - p.addAsyncListener(res -> { - onChildComplete(index, key, res); - if (res.isError()) { - assert res.getException() != null; - joined.completeExceptionally(res.getException()); - } else if (count.decrementAndGet() == -1) { - joined.complete(getResult()); - } - }); - } + p.addAsyncListener(res -> { + onChildComplete(index, key, res); + if (res.isError()) { + assert res.getException() != null; + joined.completeExceptionally(res.getException()); + } else if (count.decrementAndGet() == -1) { + joined.complete(getResult()); + } + }); } while (promises.hasNext()); if (count.decrementAndGet() == -1) { @@ -60,7 +62,7 @@ public abstract class PromiseJoiner { } } - public @NotNull Promise joined() { + public @NotNull Promise joined() { return joined; } diff --git a/futur-api/src/main/java/dev/tommyjs/futur/joiner/ResultJoiner.java b/futur-api/src/main/java/dev/tommyjs/futur/joiner/ResultJoiner.java index 9cdfe6d..b4e1a2d 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/joiner/ResultJoiner.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/joiner/ResultJoiner.java @@ -16,11 +16,11 @@ public class ResultJoiner extends PromiseJoiner, Void, T, List> public ResultJoiner( @NotNull PromiseFactory factory, @NotNull Iterator> promises, - int expectedSize, boolean link + int expectedSize ) { super(factory); this.results = new ConcurrentResultArray<>(expectedSize); - join(promises, link); + join(promises); } @Override diff --git a/futur-api/src/main/java/dev/tommyjs/futur/joiner/VoidJoiner.java b/futur-api/src/main/java/dev/tommyjs/futur/joiner/VoidJoiner.java index 673c2c7..56a58d5 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/joiner/VoidJoiner.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/joiner/VoidJoiner.java @@ -9,9 +9,9 @@ import java.util.Iterator; public class VoidJoiner extends PromiseJoiner, Void, Void, Void> { - public VoidJoiner(@NotNull PromiseFactory factory, @NotNull Iterator> promises, boolean link) { + public VoidJoiner(@NotNull PromiseFactory factory, @NotNull Iterator> promises) { super(factory); - join(promises, link); + join(promises); } @Override diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java index da542f0..7ce84d1 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/AbstractPromiseFactory.java @@ -7,10 +7,10 @@ import dev.tommyjs.futur.joiner.ResultJoiner; import dev.tommyjs.futur.joiner.VoidJoiner; import dev.tommyjs.futur.util.PromiseUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import java.util.*; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.Future; @@ -23,11 +23,7 @@ public abstract class AbstractPromiseFactory implements PromiseFactory { public abstract @NotNull PromiseExecutor getAsyncExecutor(); @Override - public @NotNull Promise wrap(@NotNull CompletableFuture future) { - return wrap(future, future); - } - - private @NotNull Promise wrap(@NotNull CompletionStage completion, Future future) { + public @NotNull Promise wrap(@NotNull CompletionStage completion, @Nullable Future future) { CompletablePromise promise = unresolved(); completion.whenComplete((v, e) -> { if (e != null) { @@ -37,62 +33,72 @@ public abstract class AbstractPromiseFactory implements PromiseFactory { } }); - promise.onCancel(_ -> future.cancel(true)); + if (future != null) { + promise.onCancel(_ -> future.cancel(true)); + } + return promise; } @Override public @NotNull Promise> combine( - @NotNull Promise p1, - @NotNull Promise p2, - boolean link + @NotNull Promise p1, @NotNull Promise p2 ) { - return all(link, p1, p2).thenApply(_ -> new AbstractMap.SimpleImmutableEntry<>( + return all(p1, p2).thenApply(_ -> new AbstractMap.SimpleImmutableEntry<>( Objects.requireNonNull(p1.getCompletion()).getResult(), Objects.requireNonNull(p2.getCompletion()).getResult() )); } @Override - public @NotNull Promise> combineMapped(@NotNull Iterator>> promises, int expectedSize, boolean link) { + public @NotNull Promise> combineMapped( + @NotNull Iterator>> promises, + int expectedSize + ) { if (!promises.hasNext()) return resolve(Collections.emptyMap()); - return new MappedResultJoiner<>(this, promises, expectedSize, link).joined(); + return new MappedResultJoiner<>(this, promises, expectedSize).joined(); } @Override public @NotNull Promise> combine( @NotNull Iterator> promises, - int expectedSize, boolean link + int expectedSize ) { if (!promises.hasNext()) return resolve(Collections.emptyList()); - return new ResultJoiner<>(this, promises, expectedSize, link).joined(); + return new ResultJoiner<>(this, promises, expectedSize).joined(); } @Override public @NotNull Promise>> allSettled( @NotNull Iterator> promises, - int expectedSize, - boolean link + int expectedSize ) { if (!promises.hasNext()) return resolve(Collections.emptyList()); - return new CompletionJoiner(this, promises, expectedSize, link).joined(); + return new CompletionJoiner(this, promises, expectedSize).joined(); } @Override - public @NotNull Promise all(@NotNull Iterator> promises, boolean link) { + public @NotNull Promise all(@NotNull Iterator> promises) { if (!promises.hasNext()) return resolve(null); - return new VoidJoiner(this, promises, link).joined(); + return new VoidJoiner(this, promises).joined(); } @Override - public @NotNull Promise race(@NotNull Iterator> promises, boolean cancelLosers) { + public @NotNull Promise race( + @NotNull Iterator> promises, + boolean ignoreErrors + ) { CompletablePromise promise = unresolved(); - promises.forEachRemaining(p -> { - if (cancelLosers) PromiseUtil.cancelOnComplete(promise, p); - if (!promise.isCompleted()) { - PromiseUtil.propagateCompletion(p, promise); + while (promises.hasNext()) { + if (promise.isCompleted()) { + promises.forEachRemaining(Promise::cancel); + break; } - }); + + Promise p = promises.next(); + PromiseUtil.cancelOnComplete(promise, p); + p.addDirectListener(promise::complete, ignoreErrors ? null : promise::completeExceptionally); + } return promise; } diff --git a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java index 901721b..0aac0c9 100644 --- a/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java +++ b/futur-api/src/main/java/dev/tommyjs/futur/promise/PromiseFactory.java @@ -3,15 +3,19 @@ package dev.tommyjs.futur.promise; import dev.tommyjs.futur.executor.PromiseExecutor; import dev.tommyjs.futur.util.PromiseUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Future; import java.util.concurrent.ScheduledExecutorService; import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; +@SuppressWarnings("unchecked") public interface PromiseFactory { /** @@ -81,480 +85,415 @@ public interface PromiseFactory { @NotNull Promise error(@NotNull Throwable error); /** - * Creates a new promise backed by the given future. The promise will be completed upon completion - * of the future. + * Creates a new promise backed by the given completion and future. + * The promise will be completed upon completion of the {@link CompletionStage} + * and the {@link Future} will be cancelled upon cancellation of the promise. + * + * @param completion the completion stage to wrap + * @param future the future to wrap + * @return the new promise + */ + @NotNull Promise wrap(@NotNull CompletionStage completion, @Nullable Future future); + + /** + * Creates a new promise backed by the given future. + * The promise will be completed upon completion of the {@link CompletableFuture} + * and the {@link CompletableFuture} will be cancelled upon cancellation of the promise. * * @param future the future to wrap * @return the new promise */ - @NotNull Promise wrap(@NotNull CompletableFuture future); + default @NotNull Promise wrap(@NotNull CompletableFuture future) { + return wrap(future, future); + }; /** - * Combines two promises into a single promise that completes when both promises complete. If - * {@code link} is {@code true} and either input promise completes exceptionally (including - * cancellation), the other promise will be cancelled and the output promise will complete - * exceptionally. + * Combines two promises into a single promise that resolves when both promises are completed. + * If either input promise completes exceptionally, the other promise will be cancelled + * and the output promise will complete exceptionally. * * @param p1 the first promise * @param p2 the second promise - * @param link whether to cancel the other promise on error * @return the combined promise */ - @NotNull Promise> combine(@NotNull Promise p1, @NotNull Promise p2, - boolean link); + @NotNull Promise> combine(@NotNull Promise p1, @NotNull Promise p2); + /** - * Combines two promises into a single promise that completes when both promises complete. If either - * input promise completes exceptionally, the other promise will be cancelled and the output promise - * will complete exceptionally. - * - * @param p1 the first promise - * @param p2 the second promise - * @return the combined promise - */ - default @NotNull Promise> combine(@NotNull Promise p1, @NotNull Promise p2) { - return combine(p1, p2, true); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions + * @param expectedSize the expected size of the iterator (used for optimization) * @return the combined promise */ @NotNull Promise> combineMapped(@NotNull Iterator>> promises, - int expectedSize, boolean link); + int expectedSize); /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ - default @NotNull Promise> combineMapped(@NotNull Collection>> promises, - boolean link) { - return combineMapped(promises.iterator(), promises.size(), link); + default @NotNull Promise> combineMapped(@NotNull Spliterator>> promises) { + return combineMapped(Spliterators.iterator(promises), PromiseUtil.estimateSize(promises)); } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise> combineMapped(@NotNull Map> promises, - boolean link) { - return combineMapped(promises.entrySet().iterator(), promises.size(), link); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. - * - * @param promises the input promises - * @return the combined promise - */ - default @NotNull Promise> combineMapped(@NotNull Map> promises) { - return combineMapped(promises, true); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. - * - * @param promises the input promises - * @return the combined promise - */ - default @NotNull Promise> combineMapped(@NotNull Collection>> promises) { - return combineMapped(promises, true); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise> combineMapped(@NotNull Stream>> promises, - boolean link) { - Spliterator>> spliterator = promises.spliterator(); - return combineMapped(Spliterators.iterator(spliterator), PromiseUtil.estimateSize(spliterator), link); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise> combineMapped(@NotNull Stream>> promises) { - return combineMapped(promises, true); + return combineMapped(promises.spliterator()); } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param keys the input keys - * @param mapper the function to map keys to value promises - * @param link whether to cancel all promises on any exceptional completions + * @param promises the input promises * @return the combined promise */ - default @NotNull Promise> combineMapped(@NotNull Iterable keys, - @NotNull Function> mapper, - boolean link) { - return combineMapped(StreamSupport.stream(keys.spliterator(), true) - .map(k -> new AbstractMap.SimpleImmutableEntry<>(k, mapper.apply(k))), link); + default @NotNull Promise> combineMapped(@NotNull Iterable>> promises) { + return combineMapped(promises.spliterator()); } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param keys the input keys - * @param mapper the function to map keys to value promises + * @param promises the input promises + * @return the combined promise + */ + default @NotNull Promise> combineMapped(@NotNull Map.Entry>... promises) { + return combineMapped(Arrays.spliterator(promises)); + } + + /** + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param promises the input promises + * @return the combined promise + */ + default @NotNull Promise> combineMapped(@NotNull Map> promises) { + return combineMapped(promises.entrySet().iterator(), promises.size()); + } + + /** + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param keys the keys to map to promises + * @param mapper the function to map keys to promises + * @return the combined promise + */ + default @NotNull Promise> combineMapped(@NotNull Stream keys, + @NotNull Function> mapper) { + return combineMapped(keys.map(k -> new AbstractMap.SimpleImmutableEntry<>(k, mapper.apply(k)))); + } + + /** + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param keys the keys to map to promises + * @param mapper the function to map keys to promises * @return the combined promise */ default @NotNull Promise> combineMapped(@NotNull Iterable keys, @NotNull Function> mapper) { - return combineMapped(keys, mapper, true); - } - - @Deprecated - default @NotNull Promise> combine(@NotNull Map> promises, boolean link) { - return combineMapped(promises, link); + return combineMapped(StreamSupport.stream(keys.spliterator(), false), mapper); } + /** + * @deprecated Use combineMapped instead. + */ @Deprecated default @NotNull Promise> combine(@NotNull Map> promises) { return combineMapped(promises); } /** - * Combines an iterator of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled and the output promise will complete exceptionally. If an exception - * handler is present, promises that fail will not cause this behaviour, and instead the exception - * handler will be called with the index that failed and the exception. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions + * @param expectedSize the expected size of the iterator (used for optimization) * @return the combined promise */ - @NotNull Promise> combine(@NotNull Iterator> promises, int expectedSize, - boolean link); + @NotNull Promise> combine(@NotNull Iterator> promises, int expectedSize); /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled and the output promise will complete exceptionally. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions * @return the combined promise */ - default @NotNull Promise> combine(@NotNull Collection> promises, boolean link) { - return combine(promises.iterator(), promises.size(), link); + default @NotNull Promise> combine(@NotNull Spliterator> promises) { + return combine(Spliterators.iterator(promises), PromiseUtil.estimateSize(promises)); } /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, the output promise will complete exceptionally. - * - * @param promises the input promises - * @return the combined promise - */ - default @NotNull Promise> combine(@NotNull Collection> promises) { - return combine(promises, true); - } - - /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled and the output promise will complete exceptionally. If an exception - * handler is present, promises that fail will not cause this behaviour, and instead the exception - * handler will be called with the index that failed and the exception. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise> combine(@NotNull Stream> promises, boolean link) { - Spliterator> spliterator = promises.spliterator(); - return combine(Spliterators.iterator(spliterator), PromiseUtil.estimateSize(spliterator), link); - } - - /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. The output promise will always complete successfully regardless of whether input - * promises fail. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise> combine(@NotNull Stream> promises) { - return combine(promises, true); + return combine(promises.spliterator()); } /** - * Combines an iterator of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param promises the input promises - * @param expectedSize the expected size of the list (used for optimization) - * @param link whether to cancel all promises on any exceptional completions + * @param promises the input promises + * @return the combined promise + */ + default @NotNull Promise> combine(@NotNull Iterable> promises) { + return combine(promises.spliterator()); + } + + /** + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param promises the input promises + * @return the combined promise + */ + default @NotNull Promise> combine(@NotNull Promise... promises) { + return combine(Arrays.spliterator(promises)); + } + + /** + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. + * + * @param promises the input promises + * @param expectedSize the expected size of the iterator (used for optimization) * @return the combined promise */ @NotNull Promise>> allSettled(@NotNull Iterator> promises, - int expectedSize, boolean link); + int expectedSize); /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise>> allSettled(@NotNull Collection> promises, - boolean link) { - return allSettled(promises.iterator(), promises.size(), link); - } - - /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, all other promises will be cancelled. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises * @return the combined promise */ - default @NotNull Promise>> allSettled(@NotNull Collection> promises) { - return allSettled(promises.iterator(), promises.size(), true); + default @NotNull Promise>> allSettled(@NotNull Spliterator> promises) { + return allSettled(Spliterators.iterator(promises), PromiseUtil.estimateSize(promises)); } /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise>> allSettled(@NotNull Stream> promises, - boolean link) { - Spliterator> spliterator = promises.spliterator(); - return allSettled(Spliterators.iterator(spliterator), PromiseUtil.estimateSize(spliterator), link); - } - - /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, all other promises will be cancelled. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise>> allSettled(@NotNull Stream> promises) { - return allSettled(promises, true); + return allSettled(promises.spliterator()); } /** - * Combines an array of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * - * @param link whether to cancel all promises on any exceptional completions * @param promises the input promises * @return the combined promise */ - default @NotNull Promise>> allSettled(boolean link, - @NotNull Promise... promises) { - return allSettled(Arrays.asList(promises).iterator(), promises.length, link); + default @NotNull Promise>> allSettled(@NotNull Iterable> promises) { + return allSettled(promises.spliterator()); } /** - * Combines an array of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, all other promises will be cancelled. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise>> allSettled(@NotNull Promise... promises) { - return allSettled(Arrays.asList(promises).iterator(), promises.length, true); + return allSettled(Arrays.spliterator(promises)); } /** - * Combines an iterator of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - @NotNull Promise all(@NotNull Iterator> promises, boolean link); - - /** - * Combines an iterable of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise all(@NotNull Iterable> promises, boolean link) { - return all(promises.iterator(), link); - } - - /** - * Combines an iterable of promises into a single promise that completes when all promises complete. - * If any promise completes exceptionally, all other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled + * and the output promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ - default @NotNull Promise all(@NotNull Iterable> promises) { - return all(promises.iterator(), true); - } + @NotNull Promise all(@NotNull Iterator> promises); /** - * Combines a stream of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - default @NotNull Promise all(@NotNull Stream> promises, boolean link) { - return all(promises.iterator(), link); - } - - /** - * Combines a stream of promises into a single promise that completes when all promises complete. - * If any promise completes exceptionally, all other promises will be cancelled and the output - * promise willcomplete exceptionally. + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled + * and the output promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise all(@NotNull Stream> promises) { - return all(promises.iterator(), true); + return all(promises.iterator()); } /** - * Combines an array of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled * and the output promise will complete exceptionally. * - * @param link whether to cancel all promises on any exceptional completions * @param promises the input promises * @return the combined promise */ - default @NotNull Promise all(boolean link, @NotNull Promise... promises) { - return all(Arrays.asList(promises).iterator(), link); + default @NotNull Promise all(@NotNull Iterable> promises) { + return all(promises.iterator()); } /** - * Combines an array of promises into a single promise that completes when all promises complete. - * If any promise completes exceptionally, all other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled + * and the output promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise all(@NotNull Promise... promises) { - return all(Arrays.asList(promises).iterator(), true); + return all(Arrays.asList(promises).iterator()); } /** - * Combines an iterator of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). If {@code cancelLosers} is {@code true}, all other - * promises will be cancelled when the first promise - * completes. - * - * @param promises the input promises - * @param cancelLosers whether to cancel the other promises when the first completes - * @return the combined promise - */ - @NotNull Promise race(@NotNull Iterator> promises, boolean cancelLosers); - - /** - * Combines an iterable of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). All other promises will be cancelled when the first - * promise completes. + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, if {@code cancelLosers} is {@code true}, the other promises will be cancelled + * once the combined promise is completed. * * @param promises the input promises + * @param ignoreErrors whether to ignore promises that complete exceptionally * @return the combined promise */ - default @NotNull Promise race(@NotNull Iterable> promises, boolean cancelLosers) { - return race(promises.iterator(), cancelLosers); - } + @NotNull Promise race(@NotNull Iterator> promises, boolean ignoreErrors); + /** - * Combines an iterable of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). All other promises will be cancelled when the first - * promise completes. + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, The other promises will be cancelled once the combined promise is completed. * * @param promises the input promises - */ - default @NotNull Promise race(@NotNull Iterable> promises) { - return race(promises.iterator(), true); - } - - /** - * Combines a stream of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). If {@code cancelLosers} is {@code true}, all other - * promises will be cancelled when the first promise completes. - * - * @param promises the input promises - * @param cancelLosers whether to cancel the other promises when the first completes + * @param ignoreErrors whether to ignore promises that complete exceptionally * @return the combined promise */ - default @NotNull Promise race(@NotNull Stream> promises, boolean cancelLosers) { - return race(promises.iterator(), cancelLosers); + default @NotNull Promise race(@NotNull Stream> promises, boolean ignoreErrors) { + return race(promises.iterator(), ignoreErrors); } /** - * Combines a stream of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). All other promises will be cancelled when the first - * promise completes. + * Combines multiple promises into a single promise that completes when any promise is completed. + * If the first promise completed exceptionally, the combined promise will also complete exceptionally. + * Additionally, the other promises will be cancelled once the combined promise is completed. * * @param promises the input promises * @return the combined promise */ default @NotNull Promise race(@NotNull Stream> promises) { - return race(promises.iterator(), true); + return race(promises, false); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, The other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @param ignoreErrors whether to ignore promises that complete exceptionally + * @return the combined promise + */ + default @NotNull Promise race(@NotNull Iterable> promises, boolean ignoreErrors) { + return race(promises.iterator(), ignoreErrors); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If the first promise completed exceptionally, the combined promise will also complete exceptionally. + * Additionally, the other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @return the combined promise + */ + default @NotNull Promise race(@NotNull Iterable> promises) { + return race(promises, false); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, The other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @param ignoreErrors whether to ignore promises that complete exceptionally + * @return the combined promise + */ + default @NotNull Promise race(boolean ignoreErrors, @NotNull Promise... promises) { + return race(Arrays.asList(promises), ignoreErrors); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If the first promise completed exceptionally, the combined promise will also complete exceptionally. + * Additionally, the other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @return the combined promise + */ + default @NotNull Promise race(@NotNull Promise... promises) { + return race(false, promises); } } diff --git a/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java b/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java index 8b65017..5f3a8ca 100644 --- a/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java +++ b/futur-api/src/test/java/dev/tommyjs/futur/PromiseTests.java @@ -56,6 +56,18 @@ public final class PromiseTests { assert !finished.get(); } + @Test + public void testFork() throws InterruptedException { + var finished = new AtomicBoolean(); + promises.start() + .thenRunDelayedAsync(() -> finished.set(true), 50, TimeUnit.MILLISECONDS) + .fork() + .cancel(); + + Thread.sleep(100L); + assert finished.get(); + } + @Test public void testToFuture() throws InterruptedException { assert promises.resolve(true).toFuture().getNow(false); diff --git a/futur-lazy/src/main/java/dev/tommyjs/futur/lazy/Promises.java b/futur-lazy/src/main/java/dev/tommyjs/futur/lazy/Promises.java index 85f4d28..e24fc4a 100644 --- a/futur-lazy/src/main/java/dev/tommyjs/futur/lazy/Promises.java +++ b/futur-lazy/src/main/java/dev/tommyjs/futur/lazy/Promises.java @@ -6,17 +6,21 @@ import dev.tommyjs.futur.promise.Promise; import dev.tommyjs.futur.promise.PromiseCompletion; import dev.tommyjs.futur.promise.PromiseFactory; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Spliterator; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.Future; import java.util.function.Function; import java.util.stream.Stream; +@SuppressWarnings("unchecked") public final class Promises { private static final Logger LOGGER = LoggerFactory.getLogger(Promises.class); @@ -68,8 +72,22 @@ public final class Promises { } /** - * Creates a new promise backed by the given future. The promise will be completed upon completion - * of the future. + * Creates a new promise backed by the given completion and future. + * The promise will be completed upon completion of the {@link CompletionStage} + * and the {@link Future} will be cancelled upon cancellation of the promise. + * + * @param completion the completion stage to wrap + * @param future the future to wrap + * @return the new promise + */ + public static @NotNull Promise wrap(@NotNull CompletionStage completion, @Nullable Future future) { + return factory.wrap(completion, future); + } + + /** + * Creates a new promise backed by the given future. + * The promise will be completed upon completion of the {@link CompletableFuture} + * and the {@link CompletableFuture} will be cancelled upon cancellation of the promise. * * @param future the future to wrap * @return the new promise @@ -79,25 +97,9 @@ public final class Promises { } /** - * Combines two promises into a single promise that completes when both promises complete. If - * {@code link} is {@code true} and either input promise completes exceptionally (including - * cancellation), the other promise will be cancelled and the output promise will complete - * exceptionally. - * - * @param p1 the first promise - * @param p2 the second promise - * @param link whether to cancel the other promise on error - * @return the combined promise - */ - public static @NotNull Promise> combine(@NotNull Promise p1, @NotNull Promise p2, - boolean link) { - return factory.combine(p1, p2, link); - } - - /** - * Combines two promises into a single promise that completes when both promises complete. If either - * input promise completes exceptionally, the other promise will be cancelled and the output promise - * will complete exceptionally. + * Combines two promises into a single promise that resolves when both promises are completed. + * If either input promise completes exceptionally, the other promise will be cancelled + * and the output promise will complete exceptionally. * * @param p1 the first promise * @param p2 the second promise @@ -108,91 +110,38 @@ public final class Promises { } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions + * @param promises the input promises + * @param expectedSize the expected size of the iterator (used for optimization) * @return the combined promise */ public static @NotNull Promise> combineMapped(@NotNull Iterator>> promises, - int expectedSize, boolean link) { - return factory.combineMapped(promises, expectedSize, link); + int expectedSize) { + return factory.combineMapped(promises, expectedSize); } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise> combineMapped(@NotNull Collection>> promises, - boolean link) { - return factory.combineMapped(promises, link); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise> combineMapped(@NotNull Map> promises, - boolean link) { - return factory.combineMapped(promises, link); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. - * - * @param promises the input promises - * @return the combined promise - */ - public static @NotNull Promise> combineMapped(@NotNull Map> promises) { + public static @NotNull Promise> combineMapped(@NotNull Spliterator>> promises) { return factory.combineMapped(promises); } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. - * - * @param promises the input promises - * @return the combined promise - */ - public static @NotNull Promise> combineMapped(@NotNull Collection>> promises) { - return factory.combineMapped(promises); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise> combineMapped(@NotNull Stream>> promises, - boolean link) { - return factory.combineMapped(promises, link); - } - - /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise @@ -202,29 +151,67 @@ public final class Promises { } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} - * and any promise completes exceptionally, the other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param keys the input keys - * @param mapper the function to map keys to value promises - * @param link whether to cancel all promises on any exceptional completions + * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise> combineMapped(@NotNull Iterable keys, - @NotNull Function> mapper, - boolean link) { - return factory.combineMapped(keys, mapper, link); + public static @NotNull Promise> combineMapped(@NotNull Iterable>> promises) { + return factory.combineMapped(promises); } /** - * Combines key-value pairs of inputs to promises into a single promise that completes with key-value - * pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, - * the output promise will complete exceptionally. + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param keys the input keys - * @param mapper the function to map keys to value promises + * @param promises the input promises + * @return the combined promise + */ + public static @NotNull Promise> combineMapped(@NotNull Map.Entry>... promises) { + return factory.combineMapped(promises); + } + + /** + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param promises the input promises + * @return the combined promise + */ + public static @NotNull Promise> combineMapped(@NotNull Map> promises) { + return factory.combineMapped(promises); + } + + /** + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param keys the keys to map to promises + * @param mapper the function to map keys to promises + * @return the combined promise + */ + public static @NotNull Promise> combineMapped(@NotNull Stream keys, + @NotNull Function> mapper) { + return factory.combineMapped(keys, mapper); + } + + /** + * Combines key-value pairs of promises into a single promise that completes + * when all promises are completed, with the results mapped by their keys. + * If any promise completes exceptionally, the other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param keys the keys to map to promises + * @param mapper the function to map keys to promises * @return the combined promise */ public static @NotNull Promise> combineMapped(@NotNull Iterable keys, @@ -232,75 +219,46 @@ public final class Promises { return factory.combineMapped(keys, mapper); } - @Deprecated - public static @NotNull Promise> combine(@NotNull Map> promises, boolean link) { - return factory.combine(promises, link); - } - + /** + * @deprecated Use combineMapped instead. + */ @Deprecated public static @NotNull Promise> combine(@NotNull Map> promises) { return factory.combine(promises); } /** - * Combines an iterator of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled and the output promise will complete exceptionally. If an exception - * handler is present, promises that fail will not cause this behaviour, and instead the exception - * handler will be called with the index that failed and the exception. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions + * @param promises the input promises + * @param expectedSize the expected size of the iterator (used for optimization) * @return the combined promise */ - public static @NotNull Promise> combine(@NotNull Iterator> promises, int expectedSize, - boolean link) { - return factory.combine(promises, expectedSize, link); + public static @NotNull Promise> combine(@NotNull Iterator> promises, int expectedSize) { + return factory.combine(promises, expectedSize); } /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise> combine(@NotNull Collection> promises, boolean link) { - return factory.combine(promises, link); - } - - /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, the output promise will complete exceptionally. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise> combine(@NotNull Collection> promises) { + public static @NotNull Promise> combine(@NotNull Spliterator> promises) { return factory.combine(promises); } /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled and the output promise will complete exceptionally. If an exception - * handler is present, promises that fail will not cause this behaviour, and instead the exception - * handler will be called with the index that failed and the exception. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise> combine(@NotNull Stream> promises, boolean link) { - return factory.combine(promises, link); - } - - /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. The output promise will always complete successfully regardless of whether input - * promises fail. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. * * @param promises the input promises * @return the combined promise @@ -310,65 +268,58 @@ public final class Promises { } /** - * Combines an iterator of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param promises the input promises + * @return the combined promise + */ + public static @NotNull Promise> combine(@NotNull Iterable> promises) { + return factory.combine(promises); + } + + /** + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of results in the original order. + * If any promise completes exceptionally, all other promises will be cancelled + * and the combined promise will complete exceptionally. + * + * @param promises the input promises + * @return the combined promise + */ + public static @NotNull Promise> combine(@NotNull Promise... promises) { + return factory.combine(promises); + } + + /** + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises - * @param expectedSize the expected size of the list (used for optimization) - * @param link whether to cancel all promises on any exceptional completions + * @param expectedSize the expected size of the iterator (used for optimization) * @return the combined promise */ public static @NotNull Promise>> allSettled(@NotNull Iterator> promises, - int expectedSize, boolean link) { - return factory.allSettled(promises, expectedSize, link); + int expectedSize) { + return factory.allSettled(promises, expectedSize); } /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise>> allSettled(@NotNull Collection> promises, - boolean link) { - return factory.allSettled(promises, link); - } - - /** - * Combines a collection of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, all other promises will be cancelled. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise>> allSettled(@NotNull Collection> promises) { + public static @NotNull Promise>> allSettled(@NotNull Spliterator> promises) { return factory.allSettled(promises); } /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise>> allSettled(@NotNull Stream> promises, - boolean link) { - return factory.allSettled(promises, link); - } - - /** - * Combines a stream of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, all other promises will be cancelled. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises * @return the combined promise @@ -378,23 +329,19 @@ public final class Promises { } /** - * Combines an array of promises into a single promise that completes with a list of results when all - * promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all - * other promises will be cancelled. The output promise will always complete successfully regardless - * of whether input promises fail. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * - * @param link whether to cancel all promises on any exceptional completions * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise>> allSettled(boolean link, - @NotNull Promise... promises) { - return factory.allSettled(link, promises); + public static @NotNull Promise>> allSettled(@NotNull Iterable> promises) { + return factory.allSettled(promises); } /** - * Combines an array of promises into a single promise that completes with a list of results when all - * promises complete. If any promise completes exceptionally, all other promises will be cancelled. + * Combines multiple promises into a single promise that completes when all promises + * are completed, with a list of completions in the original order. * * @param promises the input promises * @return the combined promise @@ -404,60 +351,21 @@ public final class Promises { } /** - * Combines an iterator of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise all(@NotNull Iterator> promises, boolean link) { - return factory.all(promises, link); - } - - /** - * Combines an iterable of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise all(@NotNull Iterable> promises, boolean link) { - return factory.all(promises, link); - } - - /** - * Combines an iterable of promises into a single promise that completes when all promises complete. - * If any promise completes exceptionally, all other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled + * and the output promise will complete exceptionally. * * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise all(@NotNull Iterable> promises) { + public static @NotNull Promise all(@NotNull Iterator> promises) { return factory.all(promises); } /** - * Combines a stream of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled and the output promise will complete exceptionally. - * - * @param promises the input promises - * @param link whether to cancel all promises on any exceptional completions - * @return the combined promise - */ - public static @NotNull Promise all(@NotNull Stream> promises, boolean link) { - return factory.all(promises, link); - } - - /** - * Combines a stream of promises into a single promise that completes when all promises complete. - * If any promise completes exceptionally, all other promises will be cancelled and the output - * promise willcomplete exceptionally. + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled + * and the output promise will complete exceptionally. * * @param promises the input promises * @return the combined promise @@ -467,23 +375,21 @@ public final class Promises { } /** - * Combines an array of promises into a single promise that completes when all promises complete. - * If {@code link} is {@code true} and any promise completes exceptionally, all other promises will - * be cancelled + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled * and the output promise will complete exceptionally. * - * @param link whether to cancel all promises on any exceptional completions * @param promises the input promises * @return the combined promise */ - public static @NotNull Promise all(boolean link, @NotNull Promise... promises) { - return factory.all(link, promises); + public static @NotNull Promise all(@NotNull Iterable> promises) { + return factory.all(promises); } /** - * Combines an array of promises into a single promise that completes when all promises complete. - * If any promise completes exceptionally, all other promises will be cancelled and the output - * promise will complete exceptionally. + * Combines multiple promises into a single promise that completes when all promises complete. + * If any promise completes exceptionally, all other promises will be cancelled + * and the output promise will complete exceptionally. * * @param promises the input promises * @return the combined promise @@ -493,59 +399,40 @@ public final class Promises { } /** - * Combines an iterator of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). If {@code cancelLosers} is {@code true}, all other - * promises will be cancelled when the first promise - * completes. + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, if {@code cancelLosers} is {@code true}, the other promises will be cancelled + * once the combined promise is completed. * * @param promises the input promises - * @param cancelLosers whether to cancel the other promises when the first completes + * @param ignoreErrors whether to ignore promises that complete exceptionally * @return the combined promise */ - public static @NotNull Promise race(@NotNull Iterator> promises, boolean cancelLosers) { - return factory.race(promises, cancelLosers); + public static @NotNull Promise race(@NotNull Iterator> promises, boolean ignoreErrors) { + return factory.race(promises, ignoreErrors); } /** - * Combines an iterable of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). All other promises will be cancelled when the first - * promise completes. - * - * @param promises the input promises - * @return the combined promise - */ - public static @NotNull Promise race(@NotNull Iterable> promises, boolean cancelLosers) { - return factory.race(promises, cancelLosers); - } - - /** - * Combines an iterable of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). All other promises will be cancelled when the first - * promise completes. - * - * @param promises the input promises - */ - public static @NotNull Promise race(@NotNull Iterable> promises) { - return factory.race(promises); - } - - /** - * Combines a stream of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). If {@code cancelLosers} is {@code true}, all other - * promises will be cancelled when the first promise completes. + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, The other promises will be cancelled once the combined promise is completed. * * @param promises the input promises - * @param cancelLosers whether to cancel the other promises when the first completes + * @param ignoreErrors whether to ignore promises that complete exceptionally * @return the combined promise */ - public static @NotNull Promise race(@NotNull Stream> promises, boolean cancelLosers) { - return factory.race(promises, cancelLosers); + public static @NotNull Promise race(@NotNull Stream> promises, boolean ignoreErrors) { + return factory.race(promises, ignoreErrors); } /** - * Combines a stream of promises into a single promise that completes when the first promise - * completes (successfully or exceptionally). All other promises will be cancelled when the first - * promise completes. + * Combines multiple promises into a single promise that completes when any promise is completed. + * If the first promise completed exceptionally, the combined promise will also complete exceptionally. + * Additionally, the other promises will be cancelled once the combined promise is completed. * * @param promises the input promises * @return the combined promise @@ -554,4 +441,58 @@ public final class Promises { return factory.race(promises); } + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, The other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @param ignoreErrors whether to ignore promises that complete exceptionally + * @return the combined promise + */ + public static @NotNull Promise race(@NotNull Iterable> promises, boolean ignoreErrors) { + return factory.race(promises, ignoreErrors); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If the first promise completed exceptionally, the combined promise will also complete exceptionally. + * Additionally, the other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @return the combined promise + */ + public static @NotNull Promise race(@NotNull Iterable> promises) { + return factory.race(promises); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the + * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a + * successful completion or complete with {@code null} if all promises complete exceptionally. + * Additionally, The other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @param ignoreErrors whether to ignore promises that complete exceptionally + * @return the combined promise + */ + public static @NotNull Promise race(boolean ignoreErrors, @NotNull Promise... promises) { + return factory.race(ignoreErrors, promises); + } + + /** + * Combines multiple promises into a single promise that completes when any promise is completed. + * If the first promise completed exceptionally, the combined promise will also complete exceptionally. + * Additionally, the other promises will be cancelled once the combined promise is completed. + * + * @param promises the input promises + * @return the combined promise + */ + public static @NotNull Promise race(@NotNull Promise... promises) { + return factory.race(promises); + } + } \ No newline at end of file