diff options
Diffstat (limited to 'bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java')
-rw-r--r-- | bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java | 138 |
1 files changed, 104 insertions, 34 deletions
diff --git a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java index 7067fe50a..394bce4bb 100644 --- a/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java +++ b/bundles/org.eclipse.osgi.util/src/org/osgi/util/promise/Promises.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2014, 2016). All Rights Reserved. + * Copyright (c) OSGi Alliance (2014, 2017). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package org.osgi.util.promise; -import static org.osgi.util.promise.PromiseImpl.requireNonNull; +import static java.util.Objects.requireNonNull; import java.util.ArrayList; import java.util.Arrays; @@ -38,43 +38,42 @@ public class Promises { } /** - * Create a new Promise that has been resolved with the specified value. + * Returns a new Promise that has been resolved with the specified value. * * @param <T> The value type associated with the returned Promise. * @param value The value of the resolved Promise. * @return A new Promise that has been resolved with the specified value. */ public static <T> Promise<T> resolved(T value) { - return new PromiseImpl<>(value, null); + return new PromiseImpl<>(value, null, null, null); } /** - * Create a new Promise that has been resolved with the specified failure. + * Returns a new Promise that has been resolved with the specified failure. * * @param <T> The value type associated with the returned Promise. * @param failure The failure of the resolved Promise. Must not be - * {@code null}. + * {@code null}. * @return A new Promise that has been resolved with the specified failure. */ public static <T> Promise<T> failed(Throwable failure) { - return new PromiseImpl<>(null, requireNonNull(failure)); + return new PromiseImpl<>(null, requireNonNull(failure), null, null); } /** - * Create a new Promise that is a latch on the resolution of the specified + * Returns a new Promise that is a latch on the resolution of the specified * Promises. - * * <p> - * The new Promise acts as a gate and must be resolved after all of the + * The returned Promise acts as a gate and must be resolved after all of the * specified Promises are resolved. * * @param <T> The value type of the List value associated with the returned - * Promise. + * Promise. * @param <S> A subtype of the value type of the List value associated with - * the returned Promise. + * the returned Promise. * @param promises The Promises which must be resolved before the returned - * Promise must be resolved. Must not be {@code null} and all of the - * elements in the collection must not be {@code null}. + * Promise must be resolved. Must not be {@code null} and all of + * the elements in the collection must not be {@code null}. * @return A Promise that is resolved only when all the specified Promises * are resolved. The returned Promise must be successfully resolved * with a List of the values in the order of the specified Promises @@ -87,33 +86,67 @@ public class Promises { * Promises which resolved with a failure. */ public static <T, S extends T> Promise<List<T>> all(Collection<Promise<S>> promises) { + return all(new Deferred<List<T>>(), promises); + } + + /** + * Resolves the Promise returned by the specified Deferred when the + * specified Promises are all resolved. + * <p> + * The returned Promise acts as a gate and must be resolved after all of the + * specified Promises are resolved. + * + * @param <T> The value type of the List value associated with the returned + * Promise. + * @param <S> A subtype of the value type of the List value associated with + * the returned Promise. + * @param deferred The specified Deferred is used to obtain and resolve the + * returned Promise. Must not be {@code null} and must not have + * already resolved the returned Promise. + * @param promises The Promises which must be resolved before the returned + * Promise must be resolved. Must not be {@code null} and all of + * the elements in the collection must not be {@code null}. + * @return The Promise from the specified Deferred. It is resolved only when + * all the specified Promises are resolved. The returned Promise + * must be successfully resolved with a List of the values in the + * order of the specified Promises if all the specified Promises are + * successfully resolved. The List in the returned Promise is the + * property of the caller and is modifiable. The returned Promise + * must be resolved with a failure of + * {@link FailedPromisesException} if any of the specified Promises + * are resolved with a failure. The failure + * {@link FailedPromisesException} must contain all of the specified + * Promises which resolved with a failure. + * @since 1.1 + */ + public static <T, S extends T> Promise<List<T>> all( + Deferred<List<T>> deferred, Collection<Promise<S>> promises) { if (promises.isEmpty()) { List<T> result = new ArrayList<>(); - return resolved(result); - } - /* make a copy and capture the ordering */ - List<Promise< ? extends T>> list = new ArrayList<Promise< ? extends T>>( - promises); - PromiseImpl<List<T>> chained = new PromiseImpl<>(); - All<T> all = new All<>(chained, list); - for (Promise<? extends T> promise : list) { - promise.onResolve(all); + deferred.resolve(result); + } else { + /* make a copy and capture the ordering */ + List<Promise< ? extends T>> list = new ArrayList<Promise< ? extends T>>( + promises); + All<T> all = new All<>(deferred, list); + for (Promise< ? extends T> promise : list) { + promise.onResolve(all); + } } - return chained; + return deferred.getPromise(); } /** - * Create a new Promise that is a latch on the resolution of the specified + * Returns a new Promise that is a latch on the resolution of the specified * Promises. - * * <p> * The new Promise acts as a gate and must be resolved after all of the * specified Promises are resolved. * * @param <T> The value type associated with the specified Promises. * @param promises The Promises which must be resolved before the returned - * Promise must be resolved. Must not be {@code null} and all of the - * arguments must not be {@code null}. + * Promise must be resolved. Must not be {@code null} and all of + * the arguments must not be {@code null}. * @return A Promise that is resolved only when all the specified Promises * are resolved. The returned Promise must be successfully resolved * with a List of the values in the order of the specified Promises @@ -133,17 +166,55 @@ public class Promises { } /** - * A callback used to resolve a Promise when the specified list of Promises + * Resolves the Promise returned by the specified Deferred when the + * specified Promises are all resolved. + * <p> + * The new Promise acts as a gate and must be resolved after all of the + * specified Promises are resolved. + * + * @param <T> The value type associated with the specified Promises. + * @param deferred The specified Deferred is used to obtain and resolve the + * returned Promise. Must not be {@code null} and must not have + * already resolved the returned Promise. + * @param promises The Promises which must be resolved before the returned + * Promise must be resolved. Must not be {@code null} and all of + * the arguments must not be {@code null}. + * @return The Promise from the specified Deferred. It is resolved only when + * all the specified Promises are resolved. The returned Promise + * must be successfully resolved with a List of the values in the + * order of the specified Promises if all the specified Promises are + * successfully resolved. The List in the returned Promise is the + * property of the caller and is modifiable. The returned Promise + * must be resolved with a failure of + * {@link FailedPromisesException} if any of the specified Promises + * are resolved with a failure. The failure + * {@link FailedPromisesException} must contain all of the specified + * Promises which resolved with a failure. + * @since 1.1 + */ + @SafeVarargs + public static <T> Promise<List<T>> all(Deferred<List<T>> deferred, + Promise< ? extends T>... promises) { + @SuppressWarnings("unchecked") + List<Promise<T>> list = Arrays.asList((Promise<T>[]) promises); + return all(deferred, list); + } + + /** + * A callback used to resolve a Deferred when the specified list of Promises * are resolved for the {@link Promises#all(Collection)} method. * * @ThreadSafe */ private static final class All<T> implements Runnable { - private final PromiseImpl<List<T>> chained; + private final Deferred<List<T>> chained; private final List<Promise<? extends T>> promises; private final AtomicInteger promiseCount; - All(PromiseImpl<List<T>> chained, List<Promise<? extends T>> promises) { + All(Deferred<List<T>> chained, List<Promise< ? extends T>> promises) { + if (chained.getPromise().isDone()) { + throw new IllegalStateException("Already resolved"); + } this.chained = chained; this.promises = promises; this.promiseCount = new AtomicInteger(promises.size()); @@ -169,10 +240,9 @@ public class Promises { } } if (failed.isEmpty()) { - chained.tryResolve(value, null); + chained.resolve(value); } else { - chained.tryResolve(null, - new FailedPromisesException(failed, cause)); + chained.fail(new FailedPromisesException(failed, cause)); } } } |