Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.activej.promise.Promises Maven / Gradle / Ivy
Go to download
A convenient way to organize asynchronous code.
Promises are a faster and more efficient version of JavaScript's Promise and Java's CompletionStage's.
/*
* Copyright (C) 2020 ActiveJ LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.activej.promise;
import io.activej.async.AsyncAccumulator;
import io.activej.async.AsyncBuffer;
import io.activej.async.exception.AsyncTimeoutException;
import io.activej.async.function.AsyncFunction;
import io.activej.async.function.AsyncRunnable;
import io.activej.async.function.AsyncSupplier;
import io.activej.common.annotation.StaticFactories;
import io.activej.common.function.BiConsumerEx;
import io.activej.common.function.FunctionEx;
import io.activej.common.recycle.Recyclers;
import io.activej.common.tuple.*;
import io.activej.reactor.Reactor;
import io.activej.reactor.schedule.ReactorScheduler;
import io.activej.reactor.schedule.ScheduledRunnable;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Array;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.function.*;
import java.util.stream.Collector;
import java.util.stream.Stream;
import static io.activej.common.Utils.iteratorOf;
import static io.activej.common.Utils.transformIterator;
import static io.activej.common.exception.FatalErrorHandler.handleError;
import static io.activej.promise.PromisePredicates.isResult;
import static io.activej.reactor.Reactor.getCurrentReactor;
import static java.util.Arrays.asList;
/**
* Allows managing multiple {@link Promise}s.
*/
@SuppressWarnings({"WeakerAccess", "unchecked", "RedundantCast"})
@StaticFactories(Promise.class)
public class Promises {
/**
* @see #timeout(long, Promise)
*/
@Contract(pure = true)
public static Promise timeout(Duration delay, Promise promise) {
return timeout((ReactorScheduler) getCurrentReactor(), delay, promise);
}
public static Promise timeout(ReactorScheduler reactor, Duration delay, Promise promise) {
return timeout(reactor, delay.toMillis(), promise);
}
/**
* Waits until the delay passes and if the {@code Promise} is still
* not complete, tries to complete it with {@code TIMEOUT_EXCEPTION}.
*
* @param delay time of delay
* @param promise the Promise to be tracked
* @return {@code Promise}
*/
@Contract(pure = true)
public static Promise timeout(long delay, Promise promise) {
return timeout((ReactorScheduler) getCurrentReactor(), delay, promise);
}
public static Promise timeout(ReactorScheduler reactor, long delay, Promise promise) {
if (promise.isComplete()) return promise;
if (delay <= 0) return Promise.ofException(new AsyncTimeoutException("Promise timeout"));
return Promise.ofCallback(cb -> {
ScheduledRunnable scheduled = new ScheduledRunnable(reactor.currentTimeMillis() + delay) {
@Override
public void run() {
cb.trySetException(new AsyncTimeoutException("Promise timeout"));
}
};
reactor.schedule(scheduled);
promise.subscribe((result, e) -> {
scheduled.cancel();
if (!cb.trySet(result, e)) {
Recyclers.recycle(result);
}
});
});
}
@Contract(pure = true)
public static Promise delay(Duration delay) {
return delay((ReactorScheduler) getCurrentReactor(), delay);
}
public static Promise delay(ReactorScheduler reactor, Duration delay) {
return delay(reactor, delay.toMillis());
}
@Contract(pure = true)
public static Promise delay(long delayMillis) {
return delay((ReactorScheduler) getCurrentReactor(), delayMillis);
}
public static Promise delay(ReactorScheduler reactor, long delayMillis) {
if (delayMillis <= 0) return Promise.of(null);
return Promise.ofCallback(cb ->
reactor.schedule(new ScheduledRunnable(reactor.currentTimeMillis() + delayMillis) {
@Override
public void run() {
cb.set(null);
}
}));
}
@Contract(pure = true)
public static Promise delay(Duration delay, T value) {
return delay((ReactorScheduler) getCurrentReactor(), delay, value);
}
public static Promise delay(ReactorScheduler reactor, Duration delay, T value) {
return delay(reactor, delay.toMillis(), value);
}
@Contract(pure = true)
public static Promise delay(long delayMillis, T value) {
return delay((ReactorScheduler) getCurrentReactor(), delayMillis, value);
}
public static Promise delay(ReactorScheduler reactor, long delayMillis, T value) {
if (delayMillis <= 0) return Promise.of(value);
return Promise.ofCallback(cb ->
reactor.schedule(new ScheduledRunnable(reactor.currentTimeMillis() + delayMillis) {
@Override
public void run() {
cb.set(value);
}
}));
}
/**
* @see #delay(long, Promise)
*/
@Contract(pure = true)
public static Promise delay(Duration delay, Promise promise) {
return delay((ReactorScheduler) getCurrentReactor(), delay, promise);
}
public static Promise delay(ReactorScheduler reactor, Duration delay, Promise promise) {
return delay(reactor, delay.toMillis(), promise);
}
/**
* Delays completion of provided {@code promise} for
* the defined period of time.
*
* @param delayMillis delay in millis
* @param promise the {@code Promise} to be delayed
* @return completed {@code Promise}
*/
@Contract(pure = true)
public static Promise delay(long delayMillis, Promise promise) {
return delay((ReactorScheduler) getCurrentReactor(), delayMillis, promise);
}
public static Promise delay(ReactorScheduler reactor, long delayMillis, Promise promise) {
if (delayMillis <= 0) return promise;
return Promise.ofCallback(cb ->
reactor.schedule(new ScheduledRunnable(reactor.currentTimeMillis() + delayMillis) {
@Override
public void run() {
promise.subscribe(cb);
}
}));
}
@Contract(pure = true)
public static Promise interval(Duration interval, Promise promise) {
return interval((ReactorScheduler) getCurrentReactor(), interval, promise);
}
public static Promise interval(ReactorScheduler reactor, Duration interval, Promise promise) {
return interval(reactor, interval.toMillis(), promise);
}
@Contract(pure = true)
public static Promise interval(long intervalMillis, Promise promise) {
return interval((ReactorScheduler) getCurrentReactor(), intervalMillis, promise);
}
public static Promise interval(ReactorScheduler reactor, long intervalMillis, Promise promise) {
return intervalMillis <= 0 ?
promise :
promise.then(value -> delay(reactor, intervalMillis, value));
}
/**
* @see #schedule(long, Promise)
*/
@Contract(pure = true)
public static Promise schedule(Instant instant) {
return schedule((ReactorScheduler) getCurrentReactor(), instant);
}
public static Promise schedule(ReactorScheduler reactor, Instant instant) {
return schedule(reactor, instant.toEpochMilli());
}
/**
* @see #schedule(long, Promise)
*/
@Contract(pure = true)
public static Promise schedule(long timestamp) {
return schedule((ReactorScheduler) getCurrentReactor(), timestamp);
}
public static Promise schedule(ReactorScheduler reactor, long timestamp) {
return Promise.ofCallback(cb ->
reactor.schedule(new ScheduledRunnable(timestamp) {
@Override
public void run() {
cb.set(null);
}
}));
}
/**
* @see #schedule(long, Promise)
*/
@Contract(pure = true)
public static Promise schedule(Instant instant, T value) {
return schedule((ReactorScheduler) getCurrentReactor(), instant.toEpochMilli(), value);
}
public static Promise schedule(ReactorScheduler reactor, Instant instant, T value) {
return schedule(reactor, instant.toEpochMilli(), value);
}
/**
* @see #schedule(long, Promise)
*/
@Contract(pure = true)
public static Promise schedule(long timestamp, T value) {
return schedule((ReactorScheduler) getCurrentReactor(), timestamp, value);
}
public static Promise schedule(ReactorScheduler reactor, long timestamp, T value) {
return Promise.ofCallback(cb ->
reactor.schedule(new ScheduledRunnable(timestamp) {
@Override
public void run() {
cb.set(value);
}
}));
}
/**
* @see #schedule(long, Promise)
*/
@Contract(pure = true)
public static Promise schedule(Instant instant, Promise promise) {
return schedule((ReactorScheduler) getCurrentReactor(), instant, promise);
}
public static Promise schedule(ReactorScheduler reactor, Instant instant, Promise promise) {
return schedule(reactor, instant.toEpochMilli(), promise);
}
/**
* Schedules completion of the {@code Promise} so that it will
* be completed after the timestamp even if its operations
* were completed earlier.
*/
@Contract(pure = true)
public static Promise schedule(long timestamp, Promise promise) {
return schedule((ReactorScheduler) getCurrentReactor(), timestamp, promise);
}
public static Promise schedule(ReactorScheduler reactor, long timestamp, Promise promise) {
return Promise.ofCallback(cb -> reactor.schedule(new ScheduledRunnable(timestamp) {
@Override
public void run() {
promise.subscribe(cb);
}
}));
}
/**
* @see Promises#all(List)
*/
@Contract(pure = true)
public static Promise all() {
return Promise.complete();
}
/**
* @see Promises#all(List)
*/
@Contract(pure = true)
public static Promise all(Promise> promise1) {
return promise1.toVoid();
}
/**
* Optimized for 2 promises.
*
* @see Promises#all(List)
*/
@Contract(pure = true)
public static Promise all(Promise> promise1, Promise> promise2) {
return promise1.both(promise2);
}
/**
* @see Promises#all(List)
*/
@Contract(pure = true)
public static Promise all(Promise>... promises) {
return all(List.of(promises));
}
/**
* Returns a {@code Promise} that completes when
* all of the {@code promises} are completed.
*/
@Contract(pure = true)
public static Promise all(List extends Promise>> promises) {
int size = promises.size();
if (size == 0) return Promise.complete();
if (size == 1) return promises.get(0).map(AbstractPromise::recycleToVoid);
if (size == 2) return promises.get(0).both(promises.get(1));
return allIterator(promises.iterator(), true);
}
/**
* @see Promises#all(List)
*/
@Contract(pure = true)
public static Promise all(Stream extends Promise>> promises) {
return all(promises.iterator());
}
/**
* Returns {@code Promise} that completes when all of the {@code promises}
* are completed. If at least one of the {@code promises} completes
* exceptionally, a {@link CompleteExceptionallyPromise} will be returned.
*/
public static Promise all(Iterator extends Promise>> promises) {
return allIterator(promises, false);
}
private static Promise allIterator(Iterator extends Promise>> promises, boolean ownership) {
if (!promises.hasNext()) return all();
PromiseAll resultPromise = new PromiseAll<>();
while (promises.hasNext()) {
Promise> promise = promises.next();
if (promise.isResult()) {
Recyclers.recycle(promise.getResult());
continue;
}
if (promise.isException()) {
if (ownership) {
promises.forEachRemaining(Recyclers::recycle);
} else {
Recyclers.recycle(promises);
}
return Promise.ofException(promise.getException());
}
resultPromise.countdown++;
promise.next(resultPromise);
}
resultPromise.countdown--;
return resultPromise.countdown == 0 ? Promise.complete() : resultPromise;
}
/**
* Returns a {@link CompleteExceptionallyPromise} with {@link Exception},
* since this method doesn't accept any {@code Promise}s
*
* @see #any(Iterator)
*/
@Contract(pure = true)
public static Promise any() {
return Promise.ofException(new Exception("There are no promises to be complete"));
}
/**
* @see #any(Iterator)
*/
@Contract(pure = true)
public static Promise any(Promise extends T> promise1) {
return (Promise) promise1;
}
/**
* Optimized for 2 promises.
*
* @see #any(Iterator)
*/
@Contract(pure = true)
public static Promise any(Promise extends T> promise1, Promise extends T> promise2) {
return ((Promise) promise1).either(promise2);
}
/**
* @see #any(Iterator)
*/
@Contract(pure = true)
@SafeVarargs
public static Promise any(Promise extends T>... promises) {
return any(isResult(), List.of(promises));
}
/**
* @see #any(Iterator)
*/
@Contract(pure = true)
public static Promise any(List extends Promise extends T>> promises) {
int size = promises.size();
if (size == 0) return any();
if (size == 1) return (Promise) promises.get(0);
if (size == 2) return ((Promise) promises.get(0)).either(promises.get(1));
return any(isResult(), promises);
}
/**
* @see #any(Iterator)
*/
@Contract(pure = true)
public static Promise any(Stream extends Promise extends T>> promises) {
return any(isResult(), promises.iterator());
}
public static Promise any(Iterator extends Promise extends T>> promises) {
return any(isResult(), promises);
}
@Contract(pure = true)
public static Promise any(BiPredicate super T, Exception> predicate, Promise extends T> promise1) {
return any(predicate, List.of(promise1));
}
@Contract(pure = true)
public static Promise any(BiPredicate super T, Exception> predicate, Promise extends T> promise1, Promise extends T> promise2) {
return any(predicate, List.of(promise1, promise2));
}
@Contract(pure = true)
@SafeVarargs
public static Promise any(BiPredicate super T, Exception> predicate, Promise extends T>... promises) {
return any(predicate, List.of(promises));
}
@Contract(pure = true)
public static Promise any(BiPredicate super T, Exception> predicate, Stream extends Promise extends T>> promises) {
return any(predicate, promises.iterator());
}
@Contract(pure = true)
public static Promise any(BiPredicate super T, Exception> predicate, List extends Promise extends T>> promises) {
return anyIterator(predicate, promises.iterator(), true);
}
public static Promise any(BiPredicate super T, Exception> predicate, Iterator extends Promise extends T>> promises) {
return anyIterator(predicate, promises, false);
}
private static Promise anyIterator(
BiPredicate super T, Exception> predicate, Iterator extends Promise extends T>> promises,
boolean ownership
) {
if (!promises.hasNext()) return any();
PromiseAny resultPromise = new PromiseAny<>(predicate);
while (promises.hasNext()) {
Promise extends T> promise = promises.next();
if (promise.isComplete()) {
T result = promise.getResult();
if (predicate.test(result, promise.getException())) {
if (ownership) {
promises.forEachRemaining(Recyclers::recycle);
} else {
Recyclers.recycle(promises);
}
return Promise.of(result);
}
Recyclers.recycle(result);
continue;
}
resultPromise.countdown++;
promise.next(resultPromise);
}
resultPromise.countdown--;
return resultPromise.countdown == 0 ? any() : resultPromise;
}
/**
* Returns a successfully completed {@code Promise}
* with an empty list as the result.
*/
@Contract(pure = true)
public static Promise> toList() {
return Promise.of(List.of());
}
/**
* Returns a completed {@code Promise}
* with a result wrapped in {@code List}.
*/
@Contract(pure = true)
public static Promise> toList(Promise extends T> promise1) {
return promise1.map(t -> List.of(t));
}
/**
* Returns {@code Promise} with a list of {@code promise1} and {@code promise2} results.
*/
@Contract(pure = true)
public static Promise> toList(Promise extends T> promise1, Promise extends T> promise2) {
return promise1.combine(promise2, List::of);
}
/**
* @see Promises#toList(List)
*/
@Contract(pure = true)
@SafeVarargs
public static Promise> toList(Promise extends T>... promises) {
return toList(List.of(promises));
}
/**
* Reduces list of {@code Promise}s into Promise<List>.
*/
@Contract(pure = true)
public static Promise> toList(List extends Promise extends T>> promises) {
int size = promises.size();
if (size == 0) return Promise.of(List.of());
if (size == 1) return promises.get(0).map(t -> List.of(t));
if (size == 2) return promises.get(0).combine(promises.get(1), List::of);
return toListImpl(promises.iterator(), promises.size(), true);
}
/**
* @see Promises#toList(List)
*/
@Contract(pure = true)
public static Promise> toList(Stream extends Promise extends T>> promises) {
return toList(promises.iterator());
}
/**
* @see Promises#toList(List)
*/
@Contract(pure = true)
public static Promise> toList(Iterable extends Promise extends T>> promises) {
return toList(promises.iterator());
}
/**
* @see Promises#toList(List)
*/
@Contract(pure = true)
public static Promise> toList(Iterator extends Promise extends T>> promises) {
return toListImpl(promises, 10, false);
}
/**
* @see Promises#toList(List)
*/
@Contract(pure = true)
private static Promise> toListImpl(Iterator extends Promise extends T>> promises, int initialSize, boolean ownership) {
PromisesToList resultPromise = new PromisesToList<>(initialSize);
for (int i = 0; promises.hasNext() && !resultPromise.isComplete(); i++) {
resultPromise.addToList(i, promises.next());
}
if (promises.hasNext()) {
if (ownership) {
promises.forEachRemaining(Recyclers::recycle);
} else {
Recyclers.recycle(promises);
}
}
return resultPromise.countdown == 0 ? Promise.of(resultPromise.getList()) : resultPromise;
}
/**
* Returns an array of provided {@code type} and length 0
* wrapped in {@code Promise}.
*/
@Contract(pure = true)
public static Promise toArray(Class type) {
return Promise.of((T[]) Array.newInstance(type, 0));
}
/**
* Returns an array with {@code promise1} result.
*/
@Contract(pure = true)
public static Promise toArray(Class type, Promise extends T> promise1) {
return promise1.map(value -> {
T[] array = (T[]) Array.newInstance(type, 1);
array[0] = value;
return array;
});
}
/**
* Returns an array with {@code promise1} and {@code promise2} results.
*/
@Contract(pure = true)
public static Promise toArray(Class type, Promise extends T> promise1, Promise extends T> promise2) {
return promise1.combine(promise2, (value1, value2) -> {
T[] array = (T[]) Array.newInstance(type, 2);
array[0] = value1;
array[1] = value2;
return array;
});
}
/**
* @see Promises#toArray(Class, List)
*/
@Contract(pure = true)
@SafeVarargs
public static Promise toArray(Class type, Promise extends T>... promises) {
return toList(promises).map(list -> list.toArray((T[]) Array.newInstance(type, list.size())));
}
/**
* Reduces promises into Promise<Array>
*/
@Contract(pure = true)
public static Promise toArray(Class type, List extends Promise extends T>> promises) {
int size = promises.size();
if (size == 0) return toArray(type);
if (size == 1) return toArray(type, promises.get(0));
if (size == 2) return toArray(type, promises.get(0), promises.get(1));
return toList(promises).map(list -> list.toArray((T[]) Array.newInstance(type, list.size())));
}
/**
* @see Promises#toArray(Class, List)
*/
@Contract(pure = true)
public static Promise toArray(Class type, Stream extends Promise extends T>> promises) {
return toList(promises).map(list -> list.toArray((T[]) Array.newInstance(type, list.size())));
}
/**
* @see Promises#toArray(Class, List)
*/
@Contract(pure = true)
public static Promise toArray(Class type, Iterable extends Promise extends T>> promises) {
return toList(promises).map(list -> list.toArray((T[]) Array.newInstance(type, list.size())));
}
/**
* @see Promises#toArray(Class, List)
*/
@Contract(pure = true)
public static Promise toArray(Class type, Iterator extends Promise extends T>> promises) {
return toList(promises).map(list -> list.toArray((T[]) Array.newInstance(type, list.size())));
}
@Contract(pure = true)
public static Promise toTuple(TupleConstructor1 constructor, Promise extends T1> promise1) {
return promise1.map(constructor::create);
}
@Contract(pure = true)
public static Promise toTuple(
TupleConstructor2 constructor,
Promise extends T1> promise1, Promise extends T2> promise2
) {
return promise1.combine(promise2, constructor::create);
}
@Contract(pure = true)
public static Promise toTuple(
TupleConstructor3 constructor,
Promise extends T1> promise1, Promise extends T2> promise2, Promise extends T3> promise3
) {
return toList(promise1, promise2, promise3)
.map(list -> constructor.create((T1) list.get(0), (T2) list.get(1), (T3) list.get(2)));
}
@Contract(pure = true)
public static Promise toTuple(
TupleConstructor4 constructor,
Promise extends T1> promise1, Promise extends T2> promise2, Promise extends T3> promise3,
Promise extends T4> promise4
) {
return toList(promise1, promise2, promise3, promise4)
.map(list -> constructor.create((T1) list.get(0), (T2) list.get(1), (T3) list.get(2), (T4) list.get(3)));
}
@Contract(pure = true)
public static Promise toTuple(
TupleConstructor5 constructor,
Promise extends T1> promise1, Promise extends T2> promise2, Promise extends T3> promise3,
Promise extends T4> promise4, Promise extends T5> promise5
) {
return toList(promise1, promise2, promise3, promise4, promise5)
.map(list -> constructor.create((T1) list.get(0), (T2) list.get(1), (T3) list.get(2), (T4) list.get(3), (T5) list.get(4)));
}
@Contract(pure = true)
public static Promise toTuple(
TupleConstructor6 constructor,
Promise extends T1> promise1, Promise extends T2> promise2, Promise extends T3> promise3,
Promise extends T4> promise4, Promise extends T5> promise5, Promise extends T6> promise6
) {
return toList(promise1, promise2, promise3, promise4, promise5, promise6)
.map(list -> constructor.create((T1) list.get(0), (T2) list.get(1), (T3) list.get(2), (T4) list.get(3), (T5) list.get(4),
(T6) list.get(5)));
}
@Contract(pure = true)
public static Promise> toTuple(Promise extends T1> promise1) {
return promise1.map(Tuple1::new);
}
@Contract(pure = true)
public static Promise> toTuple(Promise extends T1> promise1, Promise extends T2> promise2) {
return promise1.combine(promise2, Tuple2::new);
}
@Contract(pure = true)
public static Promise> toTuple(
Promise extends T1> promise1,
Promise extends T2> promise2,
Promise extends T3> promise3
) {
return toList(promise1, promise2, promise3)
.map(list -> new Tuple3<>((T1) list.get(0), (T2) list.get(1), (T3) list.get(2)));
}
@Contract(pure = true)
public static Promise> toTuple(
Promise extends T1> promise1,
Promise extends T2> promise2,
Promise extends T3> promise3,
Promise extends T4> promise4
) {
return toList(promise1, promise2, promise3, promise4)
.map(list -> new Tuple4<>((T1) list.get(0), (T2) list.get(1), (T3) list.get(2), (T4) list.get(3)));
}
@Contract(pure = true)
public static Promise> toTuple(
Promise extends T1> promise1,
Promise extends T2> promise2,
Promise extends T3> promise3,
Promise extends T4> promise4,
Promise extends T5> promise5
) {
return toList(promise1, promise2, promise3, promise4, promise5)
.map(list -> new Tuple5<>((T1) list.get(0), (T2) list.get(1), (T3) list.get(2), (T4) list.get(3), (T5) list.get(4)));
}
@Contract(pure = true)
public static Promise> toTuple(
Promise extends T1> promise1,
Promise extends T2> promise2,
Promise extends T3> promise3,
Promise extends T4> promise4,
Promise extends T5> promise5,
Promise extends T6> promise6
) {
return toList(promise1, promise2, promise3, promise4, promise5, promise6)
.map(list -> new Tuple6<>((T1) list.get(0), (T2) list.get(1), (T3) list.get(2), (T4) list.get(3), (T5) list.get(4), (T6) list.get(5)));
}
@Contract(pure = true)
public static AsyncFunction mapTuple(
TupleConstructor1 constructor,
Function super T, T1> getter1, Function> fn1
) {
return t -> toTuple(constructor,
fn1.apply(getter1.apply(t)));
}
@Contract(pure = true)
public static AsyncFunction mapTuple(
TupleConstructor2 constructor,
Function super T, T1> getter1, Function> fn1,
Function super T, T2> getter2, Function> fn2
) {
return t -> toTuple(constructor,
fn1.apply(getter1.apply(t)),
fn2.apply(getter2.apply(t)));
}
@Contract(pure = true)
public static AsyncFunction mapTuple(
TupleConstructor3 constructor,
Function super T, T1> getter1, Function> fn1,
Function super T, T2> getter2, Function> fn2,
Function super T, T3> getter3, Function> fn3
) {
return t -> toTuple(constructor,
fn1.apply(getter1.apply(t)),
fn2.apply(getter2.apply(t)),
fn3.apply(getter3.apply(t)));
}
@Contract(pure = true)
public static AsyncFunction mapTuple(
TupleConstructor4 constructor,
Function super T, T1> getter1, Function> fn1,
Function super T, T2> getter2, Function> fn2,
Function super T, T3> getter3, Function> fn3,
Function super T, T4> getter4, Function> fn4
) {
return t -> toTuple(constructor,
fn1.apply(getter1.apply(t)),
fn2.apply(getter2.apply(t)),
fn3.apply(getter3.apply(t)),
fn4.apply(getter4.apply(t)));
}
@Contract(pure = true)
public static AsyncFunction mapTuple(
TupleConstructor5 constructor,
Function super T, T1> getter1, Function> fn1,
Function super T, T2> getter2, Function> fn2,
Function super T, T3> getter3, Function> fn3,
Function super T, T4> getter4, Function> fn4,
Function super T, T5> getter5, Function> fn5
) {
return t -> toTuple(constructor,
fn1.apply(getter1.apply(t)),
fn2.apply(getter2.apply(t)),
fn3.apply(getter3.apply(t)),
fn4.apply(getter4.apply(t)),
fn5.apply(getter5.apply(t)));
}
@Contract(pure = true)
public static AsyncFunction mapTuple(
TupleConstructor6 constructor,
Function super T, T1> getter1, Function> fn1,
Function super T, T2> getter2, Function> fn2,
Function super T, T3> getter3, Function> fn3,
Function super T, T4> getter4, Function> fn4,
Function super T, T5> getter5, Function> fn5,
Function super T, T6> getter6, Function> fn6
) {
return t -> toTuple(constructor,
fn1.apply(getter1.apply(t)),
fn2.apply(getter2.apply(t)),
fn3.apply(getter3.apply(t)),
fn4.apply(getter4.apply(t)),
fn5.apply(getter5.apply(t)),
fn6.apply(getter6.apply(t)));
}
/**
* Returns a {@link CompleteNullPromise}
*/
public static Promise sequence() {
return Promise.complete();
}
/**
* Executes an {@link AsyncRunnable}, returning a {@link Promise}
* as a mark for completion
*/
public static Promise sequence(AsyncRunnable runnable) {
return runnable.run();
}
/**
* Executes both {@link AsyncRunnable}s consequently, returning a {@link Promise}
* as a mark for completion
*/
public static Promise sequence(AsyncRunnable runnable1, AsyncRunnable runnable2) {
return runnable1.run().then(runnable2::run);
}
/**
* @see Promises#sequence(Iterator)
*/
public static Promise sequence(AsyncRunnable... runnables) {
return sequence(List.of(runnables));
}
/**
* @see Promises#sequence(Iterator)
*/
public static Promise sequence(Iterable extends AsyncRunnable> runnables) {
return sequence(transformIterator(runnables.iterator(), AsyncRunnable::run));
}
/**
* @see Promises#sequence(Iterator)
*/
public static Promise sequence(Stream extends AsyncRunnable> runnables) {
return sequence(transformIterator(runnables.iterator(), AsyncRunnable::run));
}
/**
* Calls every {@code Promise} from {@code promises} in sequence and discards
* their results.Returns a {@code SettablePromise} with {@code null} result as
* a marker when all of the {@code promises} are completed.
*
* @return {@code Promise} that completes when all {@code promises} are completed
*/
public static Promise sequence(Iterator extends Promise> promises) {
return Promise.ofCallback(cb ->
sequenceImpl(promises, cb));
}
private static void sequenceImpl(Iterator extends Promise> promises, SettableCallback cb) {
while (promises.hasNext()) {
Promise> promise = promises.next();
if (promise.isResult()) continue;
promise.subscribe((result, e) -> {
if (e == null) {
sequenceImpl(promises, cb);
} else {
cb.setException(e);
}
});
return;
}
cb.set(null);
}
/**
* Picks the first {@code Promise} that was completed without exception.
*
* @see Promises#first(BiPredicate, Iterator)
*/
@SafeVarargs
public static Promise first(AsyncSupplier extends T>... promises) {
return first(isResult(), promises);
}
/**
* @see #first(AsyncSupplier[])
* @see Promises#first(BiPredicate, Iterator)
*/
public static Promise first(Iterable extends AsyncSupplier extends T>> promises) {
return first(isResult(), promises);
}
/**
* @see #first(AsyncSupplier[])
* @see Promises#first(BiPredicate, Iterator)
*/
public static Promise first(Stream extends AsyncSupplier extends T>> promises) {
return first(isResult(), promises);
}
/**
* @see #first(AsyncSupplier[])
* @see Promises#first(BiPredicate, Iterator)
*/
public static Promise first(Iterator extends Promise extends T>> promises) {
return first(isResult(), promises);
}
/**
* @see Promises#first(BiPredicate, Iterator)
*/
@SafeVarargs
public static Promise first(
BiPredicate super T, ? super Exception> predicate, AsyncSupplier extends T>... promises
) {
return first(predicate, List.of(promises));
}
/**
* @see Promises#first(BiPredicate, Iterator)
*/
public static Promise first(
BiPredicate super T, ? super Exception> predicate, Iterable extends AsyncSupplier extends T>> promises
) {
return first(predicate, asPromises(promises));
}
/**
* @see Promises#first(BiPredicate, Iterator)
*/
public static