cleanup combine methods

This commit is contained in:
WhatCats
2025-01-10 21:15:52 +01:00
parent e4e61c4b6c
commit 4d01a8a418
9 changed files with 578 additions and 678 deletions

View File

@@ -16,11 +16,11 @@ public class CompletionJoiner extends PromiseJoiner<Promise<?>, Void, Void, List
public CompletionJoiner( public CompletionJoiner(
@NotNull PromiseFactory factory, @NotNull PromiseFactory factory,
@NotNull Iterator<Promise<?>> promises, @NotNull Iterator<Promise<?>> promises,
int expectedSize, boolean link int expectedSize
) { ) {
super(factory); super(factory);
results = new ConcurrentResultArray<>(expectedSize); results = new ConcurrentResultArray<>(expectedSize);
join(promises, link); join(promises);
} }
@Override @Override

View File

@@ -15,11 +15,11 @@ public class MappedResultJoiner<K, V> extends PromiseJoiner<Map.Entry<K, Promise
public MappedResultJoiner( public MappedResultJoiner(
@NotNull PromiseFactory factory, @NotNull PromiseFactory factory,
@NotNull Iterator<Map.Entry<K, Promise<V>>> promises, @NotNull Iterator<Map.Entry<K, Promise<V>>> promises,
int expectedSize, boolean link int expectedSize
) { ) {
super(factory); super(factory);
this.results = new ConcurrentResultArray<>(expectedSize); this.results = new ConcurrentResultArray<>(expectedSize);
join(promises, link); join(promises);
} }
@Override @Override

View File

@@ -10,49 +10,51 @@ import org.jetbrains.annotations.NotNull;
import java.util.Iterator; import java.util.Iterator;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public abstract class PromiseJoiner<V, K, T, R> { public abstract class PromiseJoiner<T, Key, Value, Result> {
private final CompletablePromise<R> joined; private final CompletablePromise<Result> joined;
protected PromiseJoiner(@NotNull PromiseFactory factory) { protected PromiseJoiner(@NotNull PromiseFactory factory) {
this.joined = factory.unresolved(); this.joined = factory.unresolved();
} }
protected abstract K getChildKey(V value); protected abstract Key getChildKey(T value);
protected abstract @NotNull Promise<T> getChildPromise(V value); protected abstract @NotNull Promise<Value> getChildPromise(T value);
protected abstract void onChildComplete(int index, K key, @NotNull PromiseCompletion<T> completion); protected abstract void onChildComplete(int index, Key key, @NotNull PromiseCompletion<Value> completion);
protected abstract R getResult(); protected abstract Result getResult();
protected void join(@NotNull Iterator<V> promises, boolean link) { protected void join(@NotNull Iterator<T> promises) {
AtomicInteger count = new AtomicInteger(); AtomicInteger count = new AtomicInteger();
int i = 0; int i = 0;
do { do {
V value = promises.next(); if (joined.isCompleted()) {
Promise<T> p = getChildPromise(value); promises.forEachRemaining(v -> getChildPromise(v).cancel());
return;
}
if (link) { T value = promises.next();
Promise<Value> p = getChildPromise(value);
if (!p.isCompleted()) {
PromiseUtil.cancelOnComplete(joined, p); PromiseUtil.cancelOnComplete(joined, p);
} }
if (!joined.isCompleted()) { count.incrementAndGet();
count.incrementAndGet(); Key key = getChildKey(value);
K key = getChildKey(value); int index = i++;
int index = i++;
p.addAsyncListener(res -> { p.addAsyncListener(res -> {
onChildComplete(index, key, res); onChildComplete(index, key, res);
if (res.isError()) { if (res.isError()) {
assert res.getException() != null; assert res.getException() != null;
joined.completeExceptionally(res.getException()); joined.completeExceptionally(res.getException());
} else if (count.decrementAndGet() == -1) { } else if (count.decrementAndGet() == -1) {
joined.complete(getResult()); joined.complete(getResult());
} }
}); });
}
} while (promises.hasNext()); } while (promises.hasNext());
if (count.decrementAndGet() == -1) { if (count.decrementAndGet() == -1) {
@@ -60,7 +62,7 @@ public abstract class PromiseJoiner<V, K, T, R> {
} }
} }
public @NotNull Promise<R> joined() { public @NotNull Promise<Result> joined() {
return joined; return joined;
} }

View File

@@ -16,11 +16,11 @@ public class ResultJoiner<T> extends PromiseJoiner<Promise<T>, Void, T, List<T>>
public ResultJoiner( public ResultJoiner(
@NotNull PromiseFactory factory, @NotNull PromiseFactory factory,
@NotNull Iterator<Promise<T>> promises, @NotNull Iterator<Promise<T>> promises,
int expectedSize, boolean link int expectedSize
) { ) {
super(factory); super(factory);
this.results = new ConcurrentResultArray<>(expectedSize); this.results = new ConcurrentResultArray<>(expectedSize);
join(promises, link); join(promises);
} }
@Override @Override

View File

@@ -9,9 +9,9 @@ import java.util.Iterator;
public class VoidJoiner extends PromiseJoiner<Promise<?>, Void, Void, Void> { public class VoidJoiner extends PromiseJoiner<Promise<?>, Void, Void, Void> {
public VoidJoiner(@NotNull PromiseFactory factory, @NotNull Iterator<Promise<?>> promises, boolean link) { public VoidJoiner(@NotNull PromiseFactory factory, @NotNull Iterator<Promise<?>> promises) {
super(factory); super(factory);
join(promises, link); join(promises);
} }
@Override @Override

View File

@@ -7,10 +7,10 @@ import dev.tommyjs.futur.joiner.ResultJoiner;
import dev.tommyjs.futur.joiner.VoidJoiner; import dev.tommyjs.futur.joiner.VoidJoiner;
import dev.tommyjs.futur.util.PromiseUtil; import dev.tommyjs.futur.util.PromiseUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@@ -23,11 +23,7 @@ public abstract class AbstractPromiseFactory<FS, FA> implements PromiseFactory {
public abstract @NotNull PromiseExecutor<FA> getAsyncExecutor(); public abstract @NotNull PromiseExecutor<FA> getAsyncExecutor();
@Override @Override
public <T> @NotNull Promise<T> wrap(@NotNull CompletableFuture<T> future) { public <T> @NotNull Promise<T> wrap(@NotNull CompletionStage<T> completion, @Nullable Future<T> future) {
return wrap(future, future);
}
private <T> @NotNull Promise<T> wrap(@NotNull CompletionStage<T> completion, Future<T> future) {
CompletablePromise<T> promise = unresolved(); CompletablePromise<T> promise = unresolved();
completion.whenComplete((v, e) -> { completion.whenComplete((v, e) -> {
if (e != null) { if (e != null) {
@@ -37,62 +33,72 @@ public abstract class AbstractPromiseFactory<FS, FA> implements PromiseFactory {
} }
}); });
promise.onCancel(_ -> future.cancel(true)); if (future != null) {
promise.onCancel(_ -> future.cancel(true));
}
return promise; return promise;
} }
@Override @Override
public <K, V> @NotNull Promise<Map.Entry<K, V>> combine( public <K, V> @NotNull Promise<Map.Entry<K, V>> combine(
@NotNull Promise<K> p1, @NotNull Promise<K> p1, @NotNull Promise<V> p2
@NotNull Promise<V> p2,
boolean link
) { ) {
return all(link, p1, p2).thenApply(_ -> new AbstractMap.SimpleImmutableEntry<>( return all(p1, p2).thenApply(_ -> new AbstractMap.SimpleImmutableEntry<>(
Objects.requireNonNull(p1.getCompletion()).getResult(), Objects.requireNonNull(p1.getCompletion()).getResult(),
Objects.requireNonNull(p2.getCompletion()).getResult() Objects.requireNonNull(p2.getCompletion()).getResult()
)); ));
} }
@Override @Override
public @NotNull <K, V> Promise<Map<K, V>> combineMapped(@NotNull Iterator<Map.Entry<K, Promise<V>>> promises, int expectedSize, boolean link) { public @NotNull <K, V> Promise<Map<K, V>> combineMapped(
@NotNull Iterator<Map.Entry<K, Promise<V>>> promises,
int expectedSize
) {
if (!promises.hasNext()) return resolve(Collections.emptyMap()); if (!promises.hasNext()) return resolve(Collections.emptyMap());
return new MappedResultJoiner<>(this, promises, expectedSize, link).joined(); return new MappedResultJoiner<>(this, promises, expectedSize).joined();
} }
@Override @Override
public <V> @NotNull Promise<List<V>> combine( public <V> @NotNull Promise<List<V>> combine(
@NotNull Iterator<Promise<V>> promises, @NotNull Iterator<Promise<V>> promises,
int expectedSize, boolean link int expectedSize
) { ) {
if (!promises.hasNext()) return resolve(Collections.emptyList()); if (!promises.hasNext()) return resolve(Collections.emptyList());
return new ResultJoiner<>(this, promises, expectedSize, link).joined(); return new ResultJoiner<>(this, promises, expectedSize).joined();
} }
@Override @Override
public @NotNull Promise<List<PromiseCompletion<?>>> allSettled( public @NotNull Promise<List<PromiseCompletion<?>>> allSettled(
@NotNull Iterator<Promise<?>> promises, @NotNull Iterator<Promise<?>> promises,
int expectedSize, int expectedSize
boolean link
) { ) {
if (!promises.hasNext()) return resolve(Collections.emptyList()); if (!promises.hasNext()) return resolve(Collections.emptyList());
return new CompletionJoiner(this, promises, expectedSize, link).joined(); return new CompletionJoiner(this, promises, expectedSize).joined();
} }
@Override @Override
public @NotNull Promise<Void> all(@NotNull Iterator<Promise<?>> promises, boolean link) { public @NotNull Promise<Void> all(@NotNull Iterator<Promise<?>> promises) {
if (!promises.hasNext()) return resolve(null); if (!promises.hasNext()) return resolve(null);
return new VoidJoiner(this, promises, link).joined(); return new VoidJoiner(this, promises).joined();
} }
@Override @Override
public <V> @NotNull Promise<V> race(@NotNull Iterator<Promise<V>> promises, boolean cancelLosers) { public <V> @NotNull Promise<V> race(
@NotNull Iterator<Promise<V>> promises,
boolean ignoreErrors
) {
CompletablePromise<V> promise = unresolved(); CompletablePromise<V> promise = unresolved();
promises.forEachRemaining(p -> { while (promises.hasNext()) {
if (cancelLosers) PromiseUtil.cancelOnComplete(promise, p); if (promise.isCompleted()) {
if (!promise.isCompleted()) { promises.forEachRemaining(Promise::cancel);
PromiseUtil.propagateCompletion(p, promise); break;
} }
});
Promise<V> p = promises.next();
PromiseUtil.cancelOnComplete(promise, p);
p.addDirectListener(promise::complete, ignoreErrors ? null : promise::completeExceptionally);
}
return promise; return promise;
} }

View File

@@ -3,15 +3,19 @@ package dev.tommyjs.futur.promise;
import dev.tommyjs.futur.executor.PromiseExecutor; import dev.tommyjs.futur.executor.PromiseExecutor;
import dev.tommyjs.futur.util.PromiseUtil; import dev.tommyjs.futur.util.PromiseUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@SuppressWarnings("unchecked")
public interface PromiseFactory { public interface PromiseFactory {
/** /**
@@ -81,480 +85,415 @@ public interface PromiseFactory {
<T> @NotNull Promise<T> error(@NotNull Throwable error); <T> @NotNull Promise<T> error(@NotNull Throwable error);
/** /**
* Creates a new promise backed by the given future. The promise will be completed upon completion * Creates a new promise backed by the given completion and future.
* of the 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
*/
<T> @NotNull Promise<T> wrap(@NotNull CompletionStage<T> completion, @Nullable Future<T> 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 * @param future the future to wrap
* @return the new promise * @return the new promise
*/ */
<T> @NotNull Promise<T> wrap(@NotNull CompletableFuture<T> future); default <T> @NotNull Promise<T> wrap(@NotNull CompletableFuture<T> future) {
return wrap(future, future);
};
/** /**
* Combines two promises into a single promise that completes when both promises complete. If * Combines two promises into a single promise that resolves when both promises are completed.
* {@code link} is {@code true} and either input promise completes exceptionally (including * If either input promise completes exceptionally, the other promise will be cancelled
* cancellation), the other promise will be cancelled and the output promise will complete * and the output promise will complete exceptionally.
* exceptionally.
* *
* @param p1 the first promise * @param p1 the first promise
* @param p2 the second promise * @param p2 the second promise
* @param link whether to cancel the other promise on error
* @return the combined promise * @return the combined promise
*/ */
<K, V> @NotNull Promise<Map.Entry<K, V>> combine(@NotNull Promise<K> p1, @NotNull Promise<V> p2, <K, V> @NotNull Promise<Map.Entry<K, V>> combine(@NotNull Promise<K> p1, @NotNull Promise<V> p2);
boolean link);
/** /**
* Combines two promises into a single promise that completes when both promises complete. If either * Combines key-value pairs of promises into a single promise that completes
* input promise completes exceptionally, the other promise will be cancelled and the output promise * when all promises are completed, with the results mapped by their keys.
* will complete exceptionally. * If any promise completes exceptionally, the other promises will be cancelled
* * and the combined promise will complete exceptionally.
* @param p1 the first promise
* @param p2 the second promise
* @return the combined promise
*/
default <K, V> @NotNull Promise<Map.Entry<K, V>> combine(@NotNull Promise<K> p1, @NotNull Promise<V> 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.
* *
* @param promises the input promises * @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 * @return the combined promise
*/ */
<K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterator<Map.Entry<K, Promise<V>>> promises, <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterator<Map.Entry<K, Promise<V>>> promises,
int expectedSize, boolean link); int expectedSize);
/** /**
* Combines key-value pairs of inputs to promises into a single promise that completes with key-value * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, * when all promises are completed, with the results mapped by their keys.
* the output promise will complete exceptionally. * If any promise completes exceptionally, the other promises will be cancelled
* and the combined promise will complete exceptionally.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Collection<Map.Entry<K, Promise<V>>> promises, default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Spliterator<Map.Entry<K, Promise<V>>> promises) {
boolean link) { return combineMapped(Spliterators.iterator(promises), PromiseUtil.estimateSize(promises));
return combineMapped(promises.iterator(), promises.size(), link);
} }
/** /**
* Combines key-value pairs of inputs to promises into a single promise that completes with key-value * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} * when all promises are completed, with the results mapped by their keys.
* and any promise completes exceptionally, the other promises will be cancelled and the output * If any promise completes exceptionally, the other promises will be cancelled
* promise will complete exceptionally. * 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map<K, Promise<V>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map<K, Promise<V>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Collection<Map.Entry<K, Promise<V>>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Stream<Map.Entry<K, Promise<V>>> promises,
boolean link) {
Spliterator<Map.Entry<K, Promise<V>>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Stream<Map.Entry<K, Promise<V>>> promises) { default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Stream<Map.Entry<K, Promise<V>>> 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 * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} * when all promises are completed, with the results mapped by their keys.
* and any promise completes exceptionally, the other promises will be cancelled and the output * If any promise completes exceptionally, the other promises will be cancelled
* promise will complete exceptionally. * and the combined promise will complete exceptionally.
* *
* @param keys the input keys * @param promises the input promises
* @param mapper the function to map keys to value promises
* @param link whether to cancel all promises on any exceptional completions
* @return the combined promise * @return the combined promise
*/ */
default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<K> keys, default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<Map.Entry<K, Promise<V>>> promises) {
@NotNull Function<K, Promise<V>> mapper, return combineMapped(promises.spliterator());
boolean link) {
return combineMapped(StreamSupport.stream(keys.spliterator(), true)
.map(k -> new AbstractMap.SimpleImmutableEntry<>(k, mapper.apply(k))), link);
} }
/** /**
* Combines key-value pairs of inputs to promises into a single promise that completes with key-value * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, * when all promises are completed, with the results mapped by their keys.
* the output promise will complete exceptionally. * If any promise completes exceptionally, the other promises will be cancelled
* and the combined promise will complete exceptionally.
* *
* @param keys the input keys * @param promises the input promises
* @param mapper the function to map keys to value promises * @return the combined promise
*/
default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map.Entry<K, Promise<V>>... 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map<K, Promise<V>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Stream<K> keys,
@NotNull Function<K, Promise<V>> 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 * @return the combined promise
*/ */
default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<K> keys, default <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<K> keys,
@NotNull Function<K, Promise<V>> mapper) { @NotNull Function<K, Promise<V>> mapper) {
return combineMapped(keys, mapper, true); return combineMapped(StreamSupport.stream(keys.spliterator(), false), mapper);
}
@Deprecated
default <K, V> @NotNull Promise<Map<K, V>> combine(@NotNull Map<K, Promise<V>> promises, boolean link) {
return combineMapped(promises, link);
} }
/**
* @deprecated Use combineMapped instead.
*/
@Deprecated @Deprecated
default <K, V> @NotNull Promise<Map<K, V>> combine(@NotNull Map<K, Promise<V>> promises) { default <K, V> @NotNull Promise<Map<K, V>> combine(@NotNull Map<K, Promise<V>> promises) {
return combineMapped(promises); return combineMapped(promises);
} }
/** /**
* Combines an iterator of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled and the output promise will complete exceptionally. If an exception * If any promise completes exceptionally, all other promises will be cancelled
* handler is present, promises that fail will not cause this behaviour, and instead the exception * and the combined promise will complete exceptionally.
* handler will be called with the index that failed and the exception.
* *
* @param promises the input promises * @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 * @return the combined promise
*/ */
<V> @NotNull Promise<List<V>> combine(@NotNull Iterator<Promise<V>> promises, int expectedSize, <V> @NotNull Promise<List<V>> combine(@NotNull Iterator<Promise<V>> promises, int expectedSize);
boolean link);
/** /**
* Combines a collection of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled and the output promise will complete exceptionally. * If any promise completes exceptionally, all other promises will be cancelled
* and the combined promise will complete exceptionally.
* *
* @param promises the input promises * @param promises the input promises
* @param link whether to cancel all promises on any exceptional completions
* @return the combined promise * @return the combined promise
*/ */
default <V> @NotNull Promise<List<V>> combine(@NotNull Collection<Promise<V>> promises, boolean link) { default <V> @NotNull Promise<List<V>> combine(@NotNull Spliterator<Promise<V>> promises) {
return combine(promises.iterator(), promises.size(), link); 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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If any promise completes exceptionally, the output promise will complete exceptionally. * are completed, with a list of results in the original order.
* * If any promise completes exceptionally, all other promises will be cancelled
* @param promises the input promises * and the combined promise will complete exceptionally.
* @return the combined promise
*/
default <V> @NotNull Promise<List<V>> combine(@NotNull Collection<Promise<V>> 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 <V> @NotNull Promise<List<V>> combine(@NotNull Stream<Promise<V>> promises, boolean link) {
Spliterator<Promise<V>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default <V> @NotNull Promise<List<V>> combine(@NotNull Stream<Promise<V>> promises) { default <V> @NotNull Promise<List<V>> combine(@NotNull Stream<Promise<V>> 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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled. The output promise will always complete successfully regardless * If any promise completes exceptionally, all other promises will be cancelled
* of whether input promises fail. * and the combined promise will complete exceptionally.
* *
* @param promises the input promises * @param promises the input promises
* @param expectedSize the expected size of the list (used for optimization) * @return the combined promise
* @param link whether to cancel all promises on any exceptional completions */
default <V> @NotNull Promise<List<V>> combine(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<List<V>> combine(@NotNull Promise<V>... 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 * @return the combined promise
*/ */
@NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Iterator<Promise<?>> promises, @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Iterator<Promise<?>> 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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of completions in the original order.
* 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<List<PromiseCompletion<?>>> allSettled(@NotNull Collection<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Collection<Promise<?>> promises) { default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Spliterator<Promise<?>> promises) {
return allSettled(promises.iterator(), promises.size(), true); 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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of completions in the original order.
* 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<List<PromiseCompletion<?>>> allSettled(@NotNull Stream<Promise<?>> promises,
boolean link) {
Spliterator<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Stream<Promise<?>> promises) { default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Stream<Promise<?>> 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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of completions in the original order.
* other promises will be cancelled. The output promise will always complete successfully regardless
* of whether input promises fail.
* *
* @param link whether to cancel all promises on any exceptional completions
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(boolean link, default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Iterable<Promise<?>> promises) {
@NotNull Promise<?>... promises) { return allSettled(promises.spliterator());
return allSettled(Arrays.asList(promises).iterator(), promises.length, link);
} }
/** /**
* Combines an array of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If any promise completes exceptionally, all other promises will be cancelled. * are completed, with a list of completions in the original order.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Promise<?>... promises) { default @NotNull Promise<List<PromiseCompletion<?>>> 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. * Combines multiple 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 * If any promise completes exceptionally, all other promises will be cancelled
* be cancelled and the output promise will complete exceptionally. * 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<Void> all(@NotNull Iterator<Promise<?>> 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<Void> all(@NotNull Iterable<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<Void> all(@NotNull Iterable<Promise<?>> promises) { @NotNull Promise<Void> all(@NotNull Iterator<Promise<?>> promises);
return all(promises.iterator(), true);
}
/** /**
* Combines a stream of promises into a single promise that completes when all promises complete. * Combines multiple 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 * If any promise completes exceptionally, all other promises will be cancelled
* be cancelled and the output promise will complete exceptionally. * 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<Void> all(@NotNull Stream<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<Void> all(@NotNull Stream<Promise<?>> promises) { default @NotNull Promise<Void> all(@NotNull Stream<Promise<?>> 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. * Combines multiple 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 * If any promise completes exceptionally, all other promises will be cancelled
* be cancelled
* and the output promise will complete exceptionally. * and the output promise will complete exceptionally.
* *
* @param link whether to cancel all promises on any exceptional completions
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<Void> all(boolean link, @NotNull Promise<?>... promises) { default @NotNull Promise<Void> all(@NotNull Iterable<Promise<?>> promises) {
return all(Arrays.asList(promises).iterator(), link); return all(promises.iterator());
} }
/** /**
* Combines an array of promises into a single promise that completes when all promises complete. * 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 * If any promise completes exceptionally, all other promises will be cancelled
* promise will complete exceptionally. * and the output promise will complete exceptionally.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default @NotNull Promise<Void> all(@NotNull Promise<?>... promises) { default @NotNull Promise<Void> 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 * Combines multiple promises into a single promise that completes when any promise is completed.
* completes (successfully or exceptionally). If {@code cancelLosers} is {@code true}, all other * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the
* promises will be cancelled when the first promise * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a
* completes. * 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
* @param promises the input promises * once the combined promise is completed.
* @param cancelLosers whether to cancel the other promises when the first completes
* @return the combined promise
*/
<V> @NotNull Promise<V> race(@NotNull Iterator<Promise<V>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @param ignoreErrors whether to ignore promises that complete exceptionally
* @return the combined promise * @return the combined promise
*/ */
default <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> promises, boolean cancelLosers) { <V> @NotNull Promise<V> race(@NotNull Iterator<Promise<V>> promises, boolean ignoreErrors);
return race(promises.iterator(), cancelLosers);
}
/** /**
* Combines an iterable of promises into a single promise that completes when the first promise * Combines multiple promises into a single promise that completes when any promise is completed.
* completes (successfully or exceptionally). All other promises will be cancelled when the first * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the
* promise completes. * 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 promises the input promises
*/ * @param ignoreErrors whether to ignore promises that complete exceptionally
default <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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
* @return the combined promise * @return the combined promise
*/ */
default <V> @NotNull Promise<V> race(@NotNull Stream<Promise<V>> promises, boolean cancelLosers) { default <V> @NotNull Promise<V> race(@NotNull Stream<Promise<V>> promises, boolean ignoreErrors) {
return race(promises.iterator(), cancelLosers); return race(promises.iterator(), ignoreErrors);
} }
/** /**
* Combines a stream of promises into a single promise that completes when the first promise * Combines multiple promises into a single promise that completes when any promise is completed.
* completes (successfully or exceptionally). All other promises will be cancelled when the first * If the first promise completed exceptionally, the combined promise will also complete exceptionally.
* promise completes. * Additionally, the other promises will be cancelled once the combined promise is completed.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
default <V> @NotNull Promise<V> race(@NotNull Stream<Promise<V>> promises) { default <V> @NotNull Promise<V> race(@NotNull Stream<Promise<V>> 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 <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<V> race(boolean ignoreErrors, @NotNull Promise<V>... 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 <V> @NotNull Promise<V> race(@NotNull Promise<V>... promises) {
return race(false, promises);
} }
} }

View File

@@ -56,6 +56,18 @@ public final class PromiseTests {
assert !finished.get(); 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 @Test
public void testToFuture() throws InterruptedException { public void testToFuture() throws InterruptedException {
assert promises.resolve(true).toFuture().getNow(false); assert promises.resolve(true).toFuture().getNow(false);

View File

@@ -6,17 +6,21 @@ import dev.tommyjs.futur.promise.Promise;
import dev.tommyjs.futur.promise.PromiseCompletion; import dev.tommyjs.futur.promise.PromiseCompletion;
import dev.tommyjs.futur.promise.PromiseFactory; import dev.tommyjs.futur.promise.PromiseFactory;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Spliterator;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.Future;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
@SuppressWarnings("unchecked")
public final class Promises { public final class Promises {
private static final Logger LOGGER = LoggerFactory.getLogger(Promises.class); 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 * Creates a new promise backed by the given completion and future.
* of the 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 <T> @NotNull Promise<T> wrap(@NotNull CompletionStage<T> completion, @Nullable Future<T> 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 * @param future the future to wrap
* @return the new promise * @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 * Combines two promises into a single promise that resolves when both promises are completed.
* {@code link} is {@code true} and either input promise completes exceptionally (including * If either input promise completes exceptionally, the other promise will be cancelled
* cancellation), the other promise will be cancelled and the output promise will complete * and the output promise will complete exceptionally.
* 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 <K, V> @NotNull Promise<Map.Entry<K, V>> combine(@NotNull Promise<K> p1, @NotNull Promise<V> 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.
* *
* @param p1 the first promise * @param p1 the first promise
* @param p2 the second 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 * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} * when all promises are completed, with the results mapped by their keys.
* and any promise completes exceptionally, the other promises will be cancelled and the output * If any promise completes exceptionally, the other promises will be cancelled
* promise will complete exceptionally. * and the combined promise will complete exceptionally.
* *
* @param promises the input promises * @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 * @return the combined promise
*/ */
public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterator<Map.Entry<K, Promise<V>>> promises, public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterator<Map.Entry<K, Promise<V>>> promises,
int expectedSize, boolean link) { int expectedSize) {
return factory.combineMapped(promises, expectedSize, link); return factory.combineMapped(promises, expectedSize);
} }
/** /**
* Combines key-value pairs of inputs to promises into a single promise that completes with key-value * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, * when all promises are completed, with the results mapped by their keys.
* the output promise will complete exceptionally. * If any promise completes exceptionally, the other promises will be cancelled
* and the combined promise will complete exceptionally.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Collection<Map.Entry<K, Promise<V>>> promises, public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Spliterator<Map.Entry<K, Promise<V>>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map<K, Promise<V>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map<K, Promise<V>> promises) {
return factory.combineMapped(promises); return factory.combineMapped(promises);
} }
/** /**
* Combines key-value pairs of inputs to promises into a single promise that completes with key-value * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, * when all promises are completed, with the results mapped by their keys.
* the output promise will complete exceptionally. * 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Collection<Map.Entry<K, Promise<V>>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Stream<Map.Entry<K, Promise<V>>> 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 * @param promises the input promises
* @return the combined promise * @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 * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If {@code link} is {@code true} * when all promises are completed, with the results mapped by their keys.
* and any promise completes exceptionally, the other promises will be cancelled and the output * If any promise completes exceptionally, the other promises will be cancelled
* promise will complete exceptionally. * and the combined promise will complete exceptionally.
* *
* @param keys the input keys * @param promises the input promises
* @param mapper the function to map keys to value promises
* @param link whether to cancel all promises on any exceptional completions
* @return the combined promise * @return the combined promise
*/ */
public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<K> keys, public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<Map.Entry<K, Promise<V>>> promises) {
@NotNull Function<K, Promise<V>> mapper, return factory.combineMapped(promises);
boolean link) {
return factory.combineMapped(keys, mapper, link);
} }
/** /**
* Combines key-value pairs of inputs to promises into a single promise that completes with key-value * Combines key-value pairs of promises into a single promise that completes
* pairs of inputs to outputs when all promises complete. If any promise completes exceptionally, * when all promises are completed, with the results mapped by their keys.
* the output promise will complete exceptionally. * If any promise completes exceptionally, the other promises will be cancelled
* and the combined promise will complete exceptionally.
* *
* @param keys the input keys * @param promises the input promises
* @param mapper the function to map keys to value promises * @return the combined promise
*/
public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map.Entry<K, Promise<V>>... 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Map<K, Promise<V>> 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 <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Stream<K> keys,
@NotNull Function<K, Promise<V>> 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 * @return the combined promise
*/ */
public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<K> keys, public static <K, V> @NotNull Promise<Map<K, V>> combineMapped(@NotNull Iterable<K> keys,
@@ -232,75 +219,46 @@ public final class Promises {
return factory.combineMapped(keys, mapper); return factory.combineMapped(keys, mapper);
} }
@Deprecated /**
public static <K, V> @NotNull Promise<Map<K, V>> combine(@NotNull Map<K, Promise<V>> promises, boolean link) { * @deprecated Use combineMapped instead.
return factory.combine(promises, link); */
}
@Deprecated @Deprecated
public static <K, V> @NotNull Promise<Map<K, V>> combine(@NotNull Map<K, Promise<V>> promises) { public static <K, V> @NotNull Promise<Map<K, V>> combine(@NotNull Map<K, Promise<V>> promises) {
return factory.combine(promises); return factory.combine(promises);
} }
/** /**
* Combines an iterator of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled and the output promise will complete exceptionally. If an exception * If any promise completes exceptionally, all other promises will be cancelled
* handler is present, promises that fail will not cause this behaviour, and instead the exception * and the combined promise will complete exceptionally.
* handler will be called with the index that failed and the exception.
* *
* @param promises the input promises * @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 * @return the combined promise
*/ */
public static <V> @NotNull Promise<List<V>> combine(@NotNull Iterator<Promise<V>> promises, int expectedSize, public static <V> @NotNull Promise<List<V>> combine(@NotNull Iterator<Promise<V>> promises, int expectedSize) {
boolean link) { return factory.combine(promises, expectedSize);
return factory.combine(promises, expectedSize, link);
} }
/** /**
* Combines a collection of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled and the output promise will complete exceptionally. * 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
*/
public static <V> @NotNull Promise<List<V>> combine(@NotNull Collection<Promise<V>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
public static <V> @NotNull Promise<List<V>> combine(@NotNull Collection<Promise<V>> promises) { public static <V> @NotNull Promise<List<V>> combine(@NotNull Spliterator<Promise<V>> promises) {
return factory.combine(promises); return factory.combine(promises);
} }
/** /**
* Combines a stream of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled and the output promise will complete exceptionally. If an exception * If any promise completes exceptionally, all other promises will be cancelled
* handler is present, promises that fail will not cause this behaviour, and instead the exception * and the combined promise will complete exceptionally.
* 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 <V> @NotNull Promise<List<V>> combine(@NotNull Stream<Promise<V>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of results in the original order.
* other promises will be cancelled. The output promise will always complete successfully regardless * If any promise completes exceptionally, all other promises will be cancelled
* of whether input promises fail. * and the combined promise will complete exceptionally.
*
* @param promises the input promises
* @return the combined promise
*/
public static <V> @NotNull Promise<List<V>> combine(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<List<V>> combine(@NotNull Promise<V>... 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 promises the input promises
* @param expectedSize the expected size of the list (used for optimization) * @param expectedSize the expected size of the iterator (used for optimization)
* @param link whether to cancel all promises on any exceptional completions
* @return the combined promise * @return the combined promise
*/ */
public static @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Iterator<Promise<?>> promises, public static @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Iterator<Promise<?>> promises,
int expectedSize, boolean link) { int expectedSize) {
return factory.allSettled(promises, expectedSize, link); return factory.allSettled(promises, expectedSize);
} }
/** /**
* Combines a collection of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of completions in the original order.
* 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<List<PromiseCompletion<?>>> allSettled(@NotNull Collection<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
public static @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Collection<Promise<?>> promises) { public static @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Spliterator<Promise<?>> promises) {
return factory.allSettled(promises); return factory.allSettled(promises);
} }
/** /**
* Combines a stream of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of completions in the original order.
* 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<List<PromiseCompletion<?>>> allSettled(@NotNull Stream<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @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 * Combines multiple promises into a single promise that completes when all promises
* promises complete. If {@code link} is {@code true} and any promise completes exceptionally, all * are completed, with a list of completions in the original order.
* other promises will be cancelled. The output promise will always complete successfully regardless
* of whether input promises fail.
* *
* @param link whether to cancel all promises on any exceptional completions
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
public static @NotNull Promise<List<PromiseCompletion<?>>> allSettled(boolean link, public static @NotNull Promise<List<PromiseCompletion<?>>> allSettled(@NotNull Iterable<Promise<?>> promises) {
@NotNull Promise<?>... promises) { return factory.allSettled(promises);
return factory.allSettled(link, promises);
} }
/** /**
* Combines an array of promises into a single promise that completes with a list of results when all * Combines multiple promises into a single promise that completes when all promises
* promises complete. If any promise completes exceptionally, all other promises will be cancelled. * are completed, with a list of completions in the original order.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @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. * Combines multiple 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 * If any promise completes exceptionally, all other promises will be cancelled
* be cancelled and the output promise will complete exceptionally. * 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<Void> all(@NotNull Iterator<Promise<?>> 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<Void> all(@NotNull Iterable<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
public static @NotNull Promise<Void> all(@NotNull Iterable<Promise<?>> promises) { public static @NotNull Promise<Void> all(@NotNull Iterator<Promise<?>> promises) {
return factory.all(promises); return factory.all(promises);
} }
/** /**
* Combines a stream of promises into a single promise that completes when all promises complete. * Combines multiple 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 * If any promise completes exceptionally, all other promises will be cancelled
* be cancelled and the output promise will complete exceptionally. * 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<Void> all(@NotNull Stream<Promise<?>> 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.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @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. * Combines multiple 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 * If any promise completes exceptionally, all other promises will be cancelled
* be cancelled
* and the output promise will complete exceptionally. * and the output promise will complete exceptionally.
* *
* @param link whether to cancel all promises on any exceptional completions
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
*/ */
public static @NotNull Promise<Void> all(boolean link, @NotNull Promise<?>... promises) { public static @NotNull Promise<Void> all(@NotNull Iterable<Promise<?>> promises) {
return factory.all(link, promises); return factory.all(promises);
} }
/** /**
* Combines an array of promises into a single promise that completes when all promises complete. * 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 * If any promise completes exceptionally, all other promises will be cancelled
* promise will complete exceptionally. * and the output promise will complete exceptionally.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @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 * Combines multiple promises into a single promise that completes when any promise is completed.
* completes (successfully or exceptionally). If {@code cancelLosers} is {@code true}, all other * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the
* promises will be cancelled when the first promise * combined promise will also complete exceptionally. Otherwise, the combined promise will wait for a
* completes. * 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 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 * @return the combined promise
*/ */
public static <V> @NotNull Promise<V> race(@NotNull Iterator<Promise<V>> promises, boolean cancelLosers) { public static <V> @NotNull Promise<V> race(@NotNull Iterator<Promise<V>> promises, boolean ignoreErrors) {
return factory.race(promises, cancelLosers); return factory.race(promises, ignoreErrors);
} }
/** /**
* Combines an iterable of promises into a single promise that completes when the first promise * Combines multiple promises into a single promise that completes when any promise is completed.
* completes (successfully or exceptionally). All other promises will be cancelled when the first * If {@code ignoreErrors} is {@code false} and the first promise completed exceptionally, the
* promise completes. * 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.
* @param promises the input promises * Additionally, The other promises will be cancelled once the combined promise is completed.
* @return the combined promise
*/
public static <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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.
* *
* @param promises the input promises * @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 * @return the combined promise
*/ */
public static <V> @NotNull Promise<V> race(@NotNull Stream<Promise<V>> promises, boolean cancelLosers) { public static <V> @NotNull Promise<V> race(@NotNull Stream<Promise<V>> promises, boolean ignoreErrors) {
return factory.race(promises, cancelLosers); return factory.race(promises, ignoreErrors);
} }
/** /**
* Combines a stream of promises into a single promise that completes when the first promise * Combines multiple promises into a single promise that completes when any promise is completed.
* completes (successfully or exceptionally). All other promises will be cancelled when the first * If the first promise completed exceptionally, the combined promise will also complete exceptionally.
* promise completes. * Additionally, the other promises will be cancelled once the combined promise is completed.
* *
* @param promises the input promises * @param promises the input promises
* @return the combined promise * @return the combined promise
@@ -554,4 +441,58 @@ public final class Promises {
return factory.race(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 <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<V> race(@NotNull Iterable<Promise<V>> 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 <V> @NotNull Promise<V> race(boolean ignoreErrors, @NotNull Promise<V>... 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 <V> @NotNull Promise<V> race(@NotNull Promise<V>... promises) {
return factory.race(promises);
}
} }