--- jsr166/src/jsr166e/CompletableFuture.java 2013/05/20 16:16:42 1.17 +++ jsr166/src/jsr166e/CompletableFuture.java 2013/06/19 14:55:40 1.18 @@ -6,6 +6,7 @@ package jsr166e; import java.util.concurrent.Future; +import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.Executor; import java.util.concurrent.ThreadLocalRandom; @@ -18,52 +19,69 @@ import java.util.concurrent.locks.LockSu /** * A {@link Future} that may be explicitly completed (setting its * value and status), and may include dependent functions and actions - * that trigger upon its completion. Methods are available for adding - * those based on Functions, Blocks, and Runnables, depending on - * whether they require arguments and/or produce results, as well as - * those triggered after either or both the current and another - * CompletableFuture complete. Functions and actions supplied for - * dependent completions (mainly using methods with prefix {@code - * then}) may be performed by the thread that completes the current + * that trigger upon its completion. + * + *

When two or more threads attempt to + * {@link #complete complete}, + * {@link #completeExceptionally completeExceptionally}, or + * {@link #cancel cancel} + * a CompletableFuture, only one of them succeeds. + * + *

Methods are available for adding dependents based on + * user-provided Functions, Actions, or Runnables. The appropriate + * form to use depends on whether actions require arguments and/or + * produce results. Completion of a dependent action will trigger the + * completion of another CompletableFuture. Actions may also be + * triggered after either or both the current and another + * CompletableFuture complete. Multiple CompletableFutures may also + * be grouped as one using {@link #anyOf(CompletableFuture...)} and + * {@link #allOf(CompletableFuture...)}. + * + *

CompletableFutures themselves do not execute asynchronously. + * However, actions supplied for dependent completions of another + * CompletableFuture may do so, depending on whether they are provided + * via one of the async methods (that is, methods with names + * of the form xxxAsync). The async + * methods provide a way to commence asynchronous processing of an + * action using either a given {@link Executor} or by default the + * {@link ForkJoinPool#commonPool()}. To simplify monitoring, + * debugging, and tracking, all generated asynchronous tasks are + * instances of the marker interface {@link AsynchronousCompletionTask}. + * + *

Actions supplied for dependent completions of non-async + * methods may be performed by the thread that completes the current * CompletableFuture, or by any other caller of these methods. There * are no guarantees about the order of processing completions unless * constrained by these methods. * - *

When two or more threads attempt to {@link #complete} or {@link - * #completeExceptionally} a CompletableFuture, only one of them - * succeeds. + *

Since (unlike {@link FutureTask}) this class has no direct + * control over the computation that causes it to be completed, + * cancellation is treated as just another form of exceptional completion. + * Method {@link #cancel cancel} has the same effect as + * {@code completeExceptionally(new CancellationException())}. * - *

Upon exceptional completion, or when a completion entails - * computation of a function or action, and it terminates abruptly - * with an (unchecked) exception or error, then further completions - * act as {@code completeExceptionally} with a {@link - * CompletionException} holding that exception as its cause. If a - * CompletableFuture completes exceptionally, and is not followed by a - * {@link #exceptionally} or {@link #handle} completion, then all of - * its dependents (and their dependents) also complete exceptionally - * with CompletionExceptions holding the ultimate cause. In case of a - * CompletionException, methods {@link #get()} and {@link #get(long, - * TimeUnit)} throw an {@link ExecutionException} with the same cause - * as would be held in the corresponding CompletionException. However, - * in these cases, methods {@link #join()} and {@link #getNow} throw - * the CompletionException, which simplifies usage especially within - * other completion functions. + *

Upon exceptional completion (including cancellation), or when a + * completion entails an additional computation which terminates + * abruptly with an (unchecked) exception or error, then all of their + * dependent completions (and their dependents in turn) generally act + * as {@code completeExceptionally} with a {@link CompletionException} + * holding that exception as its cause. However, the {@link + * #exceptionally exceptionally} and {@link #handle handle} + * completions are able to handle exceptional completions of + * the CompletableFutures they depend on. * - *

CompletableFutures themselves do not execute asynchronously. - * However, the {@code async} methods provide commonly useful ways to - * commence asynchronous processing, using either a given {@link - * Executor} or by default the {@link ForkJoinPool#commonPool()}, of a - * function or action that will result in the completion of a new - * CompletableFuture. To simplify monitoring, debugging, and tracking, - * all generated asynchronous tasks are instances of the marker - * interface {@link AsynchronousCompletionTask}. + *

In case of exceptional completion with a CompletionException, + * methods {@link #get()} and {@link #get(long, TimeUnit)} throw an + * {@link ExecutionException} with the same cause as held in the + * corresponding CompletionException. However, in these cases, + * methods {@link #join()} and {@link #getNow} throw the + * CompletionException, which simplifies usage. * - *

jsr166e note: During transition, this class - * uses nested functional interfaces with different names but the - * same forms as those expected for JDK8. + *

Arguments used to pass a completion result (that is, for parameters + * of type {@code T}) may be null, but passing a null value for any other + * parameter will result in a {@link NullPointerException} being thrown. * * @author Doug Lea - * @since 1.8 */ public class CompletableFuture implements Future { // jsr166e nested interfaces @@ -110,9 +128,10 @@ public class CompletableFuture implem * extends AtomicInteger so callers can claim the action via * compareAndSet(0, 1). The Completion.run methods are all * written a boringly similar uniform way (that sometimes includes - * unnecessary-looking checks, kept to maintain uniformity). There - * are enough dimensions upon which they differ that factoring to - * use common code isn't worthwhile. + * unnecessary-looking checks, kept to maintain uniformity). + * There are enough dimensions upon which they differ that + * attempts to factor commonalities while maintaining efficiency + * require more lines of code than they would save. * * 4. The exported then/and/or methods do support a bit of * factoring (see doThenApply etc). They must cope with the @@ -169,7 +188,7 @@ public class CompletableFuture implem * CompletionException unless it is one already. Otherwise uses * the given result, boxed as NIL if null. */ - final void internalComplete(Object v, Throwable ex) { + final void internalComplete(T v, Throwable ex) { if (result == null) UNSAFE.compareAndSwapObject (this, RESULT, null, @@ -189,11 +208,14 @@ public class CompletableFuture implem /* ------------- waiting for completions -------------- */ + /** Number of processors, for spin control */ + static final int NCPU = Runtime.getRuntime().availableProcessors(); + /** * Heuristic spin value for waitingGet() before blocking on * multiprocessors */ - static final int WAITING_GET_SPINS = 256; + static final int SPINS = (NCPU > 1) ? 1 << 8 : 0; /** * Linked nodes to record waiting threads in a Treiber stack. See @@ -248,7 +270,7 @@ public class CompletableFuture implem private Object waitingGet(boolean interruptible) { WaitNode q = null; boolean queued = false; - int h = 0, spins = 0; + int spins = SPINS; for (Object r;;) { if ((r = result) != null) { if (q != null) { // suppress unpark @@ -264,15 +286,9 @@ public class CompletableFuture implem postComplete(); // help release others return r; } - else if (h == 0) { - h = ThreadLocalRandom.current().nextInt(); - if (Runtime.getRuntime().availableProcessors() > 1) - spins = WAITING_GET_SPINS; - } else if (spins > 0) { - h ^= h << 1; // xorshift - h ^= h >>> 3; - if ((h ^= h << 10) >= 0) + int rnd = ThreadLocalRandom.current().nextInt(); + if (rnd >= 0) --spins; } else if (q == null) @@ -383,6 +399,8 @@ public class CompletableFuture implem * A marker interface identifying asynchronous tasks produced by * {@code async} methods. This may be useful for monitoring, * debugging, and tracking asynchronous activities. + * + * @since 1.8 */ public static interface AsynchronousCompletionTask { } @@ -441,11 +459,11 @@ public class CompletableFuture implem } static final class AsyncApply extends Async { - final Fun fn; final T arg; + final Fun fn; final CompletableFuture dst; AsyncApply(T arg, Fun fn, - CompletableFuture dst) { + CompletableFuture dst) { this.arg = arg; this.fn = fn; this.dst = dst; } public final boolean exec() { @@ -465,14 +483,14 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class AsyncBiApply extends Async { - final BiFun fn; + static final class AsyncCombine extends Async { final T arg1; final U arg2; + final BiFun fn; final CompletableFuture dst; - AsyncBiApply(T arg1, U arg2, - BiFun fn, - CompletableFuture dst) { + AsyncCombine(T arg1, U arg2, + BiFun fn, + CompletableFuture dst) { this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; } public final boolean exec() { @@ -493,11 +511,11 @@ public class CompletableFuture implem } static final class AsyncAccept extends Async { - final Action fn; final T arg; + final Action fn; final CompletableFuture dst; AsyncAccept(T arg, Action fn, - CompletableFuture dst) { + CompletableFuture dst) { this.arg = arg; this.fn = fn; this.dst = dst; } public final boolean exec() { @@ -516,14 +534,14 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class AsyncBiAccept extends Async { - final BiAction fn; + static final class AsyncAcceptBoth extends Async { final T arg1; final U arg2; + final BiAction fn; final CompletableFuture dst; - AsyncBiAccept(T arg1, U arg2, - BiAction fn, - CompletableFuture dst) { + AsyncAcceptBoth(T arg1, U arg2, + BiAction fn, + CompletableFuture dst) { this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; } public final boolean exec() { @@ -542,6 +560,47 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } + static final class AsyncCompose extends Async { + final T arg; + final Fun> fn; + final CompletableFuture dst; + AsyncCompose(T arg, + Fun> fn, + CompletableFuture dst) { + this.arg = arg; this.fn = fn; this.dst = dst; + } + public final boolean exec() { + CompletableFuture d, fr; U u; Throwable ex; + if ((d = this.dst) != null && d.result == null) { + try { + fr = fn.apply(arg); + ex = (fr == null) ? new NullPointerException() : null; + } catch (Throwable rex) { + ex = rex; + fr = null; + } + if (ex != null) + u = null; + else { + Object r = fr.result; + if (r == null) + r = fr.waitingGet(false); + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + u = null; + } + else { + @SuppressWarnings("unchecked") U ur = (U) r; + u = ur; + } + } + d.internalComplete(u, ex); + } + return true; + } + private static final long serialVersionUID = 5232453952276885070L; + } + /* ------------- Completions -------------- */ /** @@ -560,14 +619,15 @@ public class CompletableFuture implem abstract static class Completion extends AtomicInteger implements Runnable { } - static final class ApplyCompletion extends Completion { + static final class ThenApply extends Completion { final CompletableFuture src; final Fun fn; final CompletableFuture dst; final Executor executor; - ApplyCompletion(CompletableFuture src, - Fun fn, - CompletableFuture dst, Executor executor) { + ThenApply(CompletableFuture src, + Fun fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.fn = fn; this.dst = dst; this.executor = executor; } @@ -609,14 +669,15 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class AcceptCompletion extends Completion { + static final class ThenAccept extends Completion { final CompletableFuture src; final Action fn; final CompletableFuture dst; final Executor executor; - AcceptCompletion(CompletableFuture src, - Action fn, - CompletableFuture dst, Executor executor) { + ThenAccept(CompletableFuture src, + Action fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.fn = fn; this.dst = dst; this.executor = executor; } @@ -657,20 +718,20 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class RunCompletion extends Completion { - final CompletableFuture src; + static final class ThenRun extends Completion { + final CompletableFuture src; final Runnable fn; final CompletableFuture dst; final Executor executor; - RunCompletion(CompletableFuture src, - Runnable fn, - CompletableFuture dst, - Executor executor) { + ThenRun(CompletableFuture src, + Runnable fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.fn = fn; this.dst = dst; this.executor = executor; } public final void run() { - final CompletableFuture a; + final CompletableFuture a; final Runnable fn; final CompletableFuture dst; Object r; Throwable ex; @@ -701,16 +762,17 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class BiApplyCompletion extends Completion { + static final class ThenCombine extends Completion { final CompletableFuture src; final CompletableFuture snd; final BiFun fn; final CompletableFuture dst; final Executor executor; - BiApplyCompletion(CompletableFuture src, - CompletableFuture snd, - BiFun fn, - CompletableFuture dst, Executor executor) { + ThenCombine(CompletableFuture src, + CompletableFuture snd, + BiFun fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.snd = snd; this.fn = fn; this.dst = dst; this.executor = executor; @@ -752,7 +814,7 @@ public class CompletableFuture implem if (ex == null) { try { if (e != null) - e.execute(new AsyncBiApply(t, u, fn, dst)); + e.execute(new AsyncCombine(t, u, fn, dst)); else v = fn.apply(t, u); } catch (Throwable rex) { @@ -766,16 +828,17 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class BiAcceptCompletion extends Completion { + static final class ThenAcceptBoth extends Completion { final CompletableFuture src; final CompletableFuture snd; final BiAction fn; final CompletableFuture dst; final Executor executor; - BiAcceptCompletion(CompletableFuture src, - CompletableFuture snd, - BiAction fn, - CompletableFuture dst, Executor executor) { + ThenAcceptBoth(CompletableFuture src, + CompletableFuture snd, + BiAction fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.snd = snd; this.fn = fn; this.dst = dst; this.executor = executor; @@ -816,7 +879,7 @@ public class CompletableFuture implem if (ex == null) { try { if (e != null) - e.execute(new AsyncBiAccept(t, u, fn, dst)); + e.execute(new AsyncAcceptBoth(t, u, fn, dst)); else fn.accept(t, u); } catch (Throwable rex) { @@ -830,22 +893,23 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class BiRunCompletion extends Completion { - final CompletableFuture src; + static final class RunAfterBoth extends Completion { + final CompletableFuture src; final CompletableFuture snd; final Runnable fn; final CompletableFuture dst; final Executor executor; - BiRunCompletion(CompletableFuture src, - CompletableFuture snd, - Runnable fn, - CompletableFuture dst, Executor executor) { + RunAfterBoth(CompletableFuture src, + CompletableFuture snd, + Runnable fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.snd = snd; this.fn = fn; this.dst = dst; this.executor = executor; } public final void run() { - final CompletableFuture a; + final CompletableFuture a; final CompletableFuture b; final Runnable fn; final CompletableFuture dst; @@ -881,16 +945,49 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class OrApplyCompletion extends Completion { + static final class AndCompletion extends Completion { + final CompletableFuture src; + final CompletableFuture snd; + final CompletableFuture dst; + AndCompletion(CompletableFuture src, + CompletableFuture snd, + CompletableFuture dst) { + this.src = src; this.snd = snd; this.dst = dst; + } + public final void run() { + final CompletableFuture a; + final CompletableFuture b; + final CompletableFuture dst; + Object r, s; Throwable ex; + if ((dst = this.dst) != null && + (a = this.src) != null && + (r = a.result) != null && + (b = this.snd) != null && + (s = b.result) != null && + compareAndSet(0, 1)) { + if (r instanceof AltResult) + ex = ((AltResult)r).ex; + else + ex = null; + if (ex == null && (s instanceof AltResult)) + ex = ((AltResult)s).ex; + dst.internalComplete(null, ex); + } + } + private static final long serialVersionUID = 5232453952276885070L; + } + + static final class ApplyToEither extends Completion { final CompletableFuture src; final CompletableFuture snd; final Fun fn; final CompletableFuture dst; final Executor executor; - OrApplyCompletion(CompletableFuture src, - CompletableFuture snd, - Fun fn, - CompletableFuture dst, Executor executor) { + ApplyToEither(CompletableFuture src, + CompletableFuture snd, + Fun fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.snd = snd; this.fn = fn; this.dst = dst; this.executor = executor; @@ -934,16 +1031,17 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class OrAcceptCompletion extends Completion { + static final class AcceptEither extends Completion { final CompletableFuture src; final CompletableFuture snd; final Action fn; final CompletableFuture dst; final Executor executor; - OrAcceptCompletion(CompletableFuture src, - CompletableFuture snd, - Action fn, - CompletableFuture dst, Executor executor) { + AcceptEither(CompletableFuture src, + CompletableFuture snd, + Action fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.snd = snd; this.fn = fn; this.dst = dst; this.executor = executor; @@ -986,22 +1084,23 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class OrRunCompletion extends Completion { - final CompletableFuture src; + static final class RunAfterEither extends Completion { + final CompletableFuture src; final CompletableFuture snd; final Runnable fn; final CompletableFuture dst; final Executor executor; - OrRunCompletion(CompletableFuture src, - CompletableFuture snd, - Runnable fn, - CompletableFuture dst, Executor executor) { + RunAfterEither(CompletableFuture src, + CompletableFuture snd, + Runnable fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.snd = snd; this.fn = fn; this.dst = dst; this.executor = executor; } public final void run() { - final CompletableFuture a; + final CompletableFuture a; final CompletableFuture b; final Runnable fn; final CompletableFuture dst; @@ -1033,6 +1132,38 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } + static final class OrCompletion extends Completion { + final CompletableFuture src; + final CompletableFuture snd; + final CompletableFuture dst; + OrCompletion(CompletableFuture src, + CompletableFuture snd, + CompletableFuture dst) { + this.src = src; this.snd = snd; this.dst = dst; + } + public final void run() { + final CompletableFuture a; + final CompletableFuture b; + final CompletableFuture dst; + Object r, t; Throwable ex; + if ((dst = this.dst) != null && + (((a = this.src) != null && (r = a.result) != null) || + ((b = this.snd) != null && (r = b.result) != null)) && + compareAndSet(0, 1)) { + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + t = r; + } + dst.internalComplete(t, ex); + } + } + private static final long serialVersionUID = 5232453952276885070L; + } + static final class ExceptionCompletion extends Completion { final CompletableFuture src; final Fun fn; @@ -1071,16 +1202,16 @@ public class CompletableFuture implem } static final class ThenCopy extends Completion { - final CompletableFuture src; + final CompletableFuture src; final CompletableFuture dst; - ThenCopy(CompletableFuture src, + ThenCopy(CompletableFuture src, CompletableFuture dst) { this.src = src; this.dst = dst; } public final void run() { - final CompletableFuture a; + final CompletableFuture a; final CompletableFuture dst; - Object r; Object t; Throwable ex; + Object r; T t; Throwable ex; if ((dst = this.dst) != null && (a = this.src) != null && (r = a.result) != null && @@ -1091,7 +1222,8 @@ public class CompletableFuture implem } else { ex = null; - t = r; + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; } dst.internalComplete(t, ex); } @@ -1099,13 +1231,39 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } + // version of ThenCopy for CompletableFuture dst + static final class ThenPropagate extends Completion { + final CompletableFuture src; + final CompletableFuture dst; + ThenPropagate(CompletableFuture src, + CompletableFuture dst) { + this.src = src; this.dst = dst; + } + public final void run() { + final CompletableFuture a; + final CompletableFuture dst; + Object r; Throwable ex; + if ((dst = this.dst) != null && + (a = this.src) != null && + (r = a.result) != null && + compareAndSet(0, 1)) { + if (r instanceof AltResult) + ex = ((AltResult)r).ex; + else + ex = null; + dst.internalComplete(null, ex); + } + } + private static final long serialVersionUID = 5232453952276885070L; + } + static final class HandleCompletion extends Completion { final CompletableFuture src; final BiFun fn; final CompletableFuture dst; HandleCompletion(CompletableFuture src, BiFun fn, - final CompletableFuture dst) { + CompletableFuture dst) { this.src = src; this.fn = fn; this.dst = dst; } public final void run() { @@ -1139,20 +1297,23 @@ public class CompletableFuture implem private static final long serialVersionUID = 5232453952276885070L; } - static final class ComposeCompletion extends Completion { + static final class ThenCompose extends Completion { final CompletableFuture src; final Fun> fn; final CompletableFuture dst; - ComposeCompletion(CompletableFuture src, - Fun> fn, - final CompletableFuture dst) { + final Executor executor; + ThenCompose(CompletableFuture src, + Fun> fn, + CompletableFuture dst, + Executor executor) { this.src = src; this.fn = fn; this.dst = dst; + this.executor = executor; } public final void run() { final CompletableFuture a; final Fun> fn; final CompletableFuture dst; - Object r; T t; Throwable ex; + Object r; T t; Throwable ex; Executor e; if ((dst = this.dst) != null && (fn = this.fn) != null && (a = this.src) != null && @@ -1171,17 +1332,18 @@ public class CompletableFuture implem U u = null; boolean complete = false; if (ex == null) { - try { - c = fn.apply(t); - } catch (Throwable rex) { - ex = rex; + if ((e = executor) != null) + e.execute(new AsyncCompose(t, fn, dst)); + else { + try { + if ((c = fn.apply(t)) == null) + ex = new NullPointerException(); + } catch (Throwable rex) { + ex = rex; + } } } - if (ex != null || c == null) { - if (ex == null) - ex = new NullPointerException(); - } - else { + if (c != null) { ThenCopy d = null; Object s; if ((s = c.result) == null) { @@ -1223,13 +1385,13 @@ public class CompletableFuture implem } /** - * Asynchronously executes in the {@link - * ForkJoinPool#commonPool()}, a task that completes the returned - * CompletableFuture with the result of the given Supplier. + * Returns a new CompletableFuture that is asynchronously completed + * by a task running in the {@link ForkJoinPool#commonPool()} with + * the value obtained by calling the given Generator. * * @param supplier a function returning the value to be used * to complete the returned CompletableFuture - * @return the CompletableFuture + * @return the new CompletableFuture */ public static CompletableFuture supplyAsync(Generator supplier) { if (supplier == null) throw new NullPointerException(); @@ -1240,14 +1402,14 @@ public class CompletableFuture implem } /** - * Asynchronously executes using the given executor, a task that - * completes the returned CompletableFuture with the result of the - * given Supplier. + * Returns a new CompletableFuture that is asynchronously completed + * by a task running in the given executor with the value obtained + * by calling the given Generator. * * @param supplier a function returning the value to be used * to complete the returned CompletableFuture * @param executor the executor to use for asynchronous execution - * @return the CompletableFuture + * @return the new CompletableFuture */ public static CompletableFuture supplyAsync(Generator supplier, Executor executor) { @@ -1259,13 +1421,13 @@ public class CompletableFuture implem } /** - * Asynchronously executes in the {@link - * ForkJoinPool#commonPool()} a task that runs the given action, - * and then completes the returned CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * by a task running in the {@link ForkJoinPool#commonPool()} after + * it runs the given action. * * @param runnable the action to run before completing the * returned CompletableFuture - * @return the CompletableFuture + * @return the new CompletableFuture */ public static CompletableFuture runAsync(Runnable runnable) { if (runnable == null) throw new NullPointerException(); @@ -1276,14 +1438,14 @@ public class CompletableFuture implem } /** - * Asynchronously executes using the given executor, a task that - * runs the given action, and then completes the returned - * CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * by a task running in the given executor after it runs the given + * action. * * @param runnable the action to run before completing the * returned CompletableFuture * @param executor the executor to use for asynchronous execution - * @return the CompletableFuture + * @return the new CompletableFuture */ public static CompletableFuture runAsync(Runnable runnable, Executor executor) { @@ -1295,6 +1457,19 @@ public class CompletableFuture implem } /** + * Returns a new CompletableFuture that is already completed with + * the given value. + * + * @param value the value + * @return the completed CompletableFuture + */ + public static CompletableFuture completedFuture(U value) { + CompletableFuture f = new CompletableFuture(); + f.result = (value == null) ? NIL : value; + return f; + } + + /** * Returns {@code true} if completed in any fashion: normally, * exceptionally, or via cancellation. * @@ -1305,13 +1480,12 @@ public class CompletableFuture implem } /** - * Waits if necessary for the computation to complete, and then - * retrieves its result. + * Waits if necessary for this future to complete, and then + * returns its result. * - * @return the computed result - * @throws CancellationException if the computation was cancelled - * @throws ExecutionException if the computation threw an - * exception + * @return the result value + * @throws CancellationException if this future was cancelled + * @throws ExecutionException if this future completed exceptionally * @throws InterruptedException if the current thread was interrupted * while waiting */ @@ -1334,15 +1508,14 @@ public class CompletableFuture implem } /** - * Waits if necessary for at most the given time for completion, - * and then retrieves its result, if available. + * Waits if necessary for at most the given time for this future + * to complete, and then returns its result, if available. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument - * @return the computed result - * @throws CancellationException if the computation was cancelled - * @throws ExecutionException if the computation threw an - * exception + * @return the result value + * @throws CancellationException if this future was cancelled + * @throws ExecutionException if this future completed exceptionally * @throws InterruptedException if the current thread was interrupted * while waiting * @throws TimeoutException if the wait timed out @@ -1380,8 +1553,8 @@ public class CompletableFuture implem * * @return the result value * @throws CancellationException if the computation was cancelled - * @throws CompletionException if a completion computation threw - * an exception + * @throws CompletionException if this future completed + * exceptionally or a completion computation threw an exception */ public T join() { Object r; Throwable ex; @@ -1407,8 +1580,8 @@ public class CompletableFuture implem * @param valueIfAbsent the value to return if not completed * @return the result value, if completed, else the given valueIfAbsent * @throws CancellationException if the computation was cancelled - * @throws CompletionException if a completion computation threw - * an exception + * @throws CompletionException if this future completed + * exceptionally or a completion computation threw an exception */ public T getNow(T valueIfAbsent) { Object r; Throwable ex; @@ -1460,12 +1633,14 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed with - * the result of the given function of this CompletableFuture. - * If this CompletableFuture completes exceptionally, - * then the returned CompletableFuture also does so, - * with a CompletionException holding this exception as - * its cause. + * Returns a new CompletableFuture that is completed + * when this CompletableFuture completes, with the result of the + * given function of this CompletableFuture's result. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied function throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param fn the function to use to compute the value of * the returned CompletableFuture @@ -1476,49 +1651,58 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the {@link ForkJoinPool#commonPool()} with the - * result of the given function of this CompletableFuture. If - * this CompletableFuture completes exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding this exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when this CompletableFuture completes, with the result of the + * given function of this CompletableFuture's result from a + * task running in the {@link ForkJoinPool#commonPool()}. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied function throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param fn the function to use to compute the value of * the returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture thenApplyAsync(Fun fn) { + public CompletableFuture thenApplyAsync + (Fun fn) { return doThenApply(fn, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the given executor with the result of the given - * function of this CompletableFuture. If this CompletableFuture - * completes exceptionally, then the returned CompletableFuture - * also does so, with a CompletionException holding this exception as - * its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when this CompletableFuture completes, with the result of the + * given function of this CompletableFuture's result from a + * task running in the given executor. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied function throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param fn the function to use to compute the value of * the returned CompletableFuture * @param executor the executor to use for asynchronous execution * @return the new CompletableFuture */ - public CompletableFuture thenApplyAsync(Fun fn, - Executor executor) { + public CompletableFuture thenApplyAsync + (Fun fn, + Executor executor) { if (executor == null) throw new NullPointerException(); return doThenApply(fn, executor); } - private CompletableFuture doThenApply(Fun fn, - Executor e) { + private CompletableFuture doThenApply + (Fun fn, + Executor e) { if (fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - ApplyCompletion d = null; + ThenApply d = null; Object r; if ((r = result) == null) { CompletionNode p = new CompletionNode - (d = new ApplyCompletion(this, fn, dst, e)); + (d = new ThenApply(this, fn, dst, e)); while ((r = result) == null) { if (UNSAFE.compareAndSwapObject (this, COMPLETIONS, p.next = completions, p)) @@ -1555,12 +1739,14 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed after - * performing the given action with this CompletableFuture's - * result when it completes. If this CompletableFuture - * completes exceptionally, then the returned CompletableFuture - * also does so, with a CompletionException holding this exception as - * its cause. + * Returns a new CompletableFuture that is completed + * when this CompletableFuture completes, after performing the given + * action with this CompletableFuture's result. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied action throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param block the action to perform before completing the * returned CompletableFuture @@ -1571,12 +1757,15 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the {@link ForkJoinPool#commonPool()} with this - * CompletableFuture's result when it completes. If this - * CompletableFuture completes exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding - * this exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when this CompletableFuture completes, after performing the given + * action with this CompletableFuture's result from a task running + * in the {@link ForkJoinPool#commonPool()}. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied action throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param block the action to perform before completing the * returned CompletableFuture @@ -1587,12 +1776,15 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the given executor with this - * CompletableFuture's result when it completes. If this - * CompletableFuture completes exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding - * this exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when this CompletableFuture completes, after performing the given + * action with this CompletableFuture's result from a task running + * in the given executor. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied action throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param block the action to perform before completing the * returned CompletableFuture @@ -1609,11 +1801,11 @@ public class CompletableFuture implem Executor e) { if (fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - AcceptCompletion d = null; + ThenAccept d = null; Object r; if ((r = result) == null) { CompletionNode p = new CompletionNode - (d = new AcceptCompletion(this, fn, dst, e)); + (d = new ThenAccept(this, fn, dst, e)); while ((r = result) == null) { if (UNSAFE.compareAndSwapObject (this, COMPLETIONS, p.next = completions, p)) @@ -1649,11 +1841,14 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed after - * performing the given action when this CompletableFuture - * completes. If this CompletableFuture completes exceptionally, - * then the returned CompletableFuture also does so, with a - * CompletionException holding this exception as its cause. + * Returns a new CompletableFuture that is completed + * when this CompletableFuture completes, after performing the given + * action. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied action throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param action the action to perform before completing the * returned CompletableFuture @@ -1664,12 +1859,14 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the {@link ForkJoinPool#commonPool()} after - * performing the given action when this CompletableFuture - * completes. If this CompletableFuture completes exceptionally, - * then the returned CompletableFuture also does so, with a - * CompletionException holding this exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when this CompletableFuture completes, after performing the given + * action from a task running in the {@link ForkJoinPool#commonPool()}. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied action throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param action the action to perform before completing the * returned CompletableFuture @@ -1680,12 +1877,14 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the given executor after performing the given - * action when this CompletableFuture completes. If this - * CompletableFuture completes exceptionally, then the returned - * CompletableFuture also does so, with a CompletionException holding - * this exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when this CompletableFuture completes, after performing the given + * action from a task running in the given executor. + * + *

If this CompletableFuture completes exceptionally, or the + * supplied action throws an exception, then the returned + * CompletableFuture completes exceptionally with a + * CompletionException holding the exception as its cause. * * @param action the action to perform before completing the * returned CompletableFuture @@ -1702,11 +1901,11 @@ public class CompletableFuture implem Executor e) { if (action == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - RunCompletion d = null; + ThenRun d = null; Object r; if ((r = result) == null) { CompletionNode p = new CompletionNode - (d = new RunCompletion(this, action, dst, e)); + (d = new ThenRun(this, action, dst, e)); while ((r = result) == null) { if (UNSAFE.compareAndSwapObject (this, COMPLETIONS, p.next = completions, p)) @@ -1737,50 +1936,60 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed with - * the result of the given function of this and the other given - * CompletableFuture's results when both complete. If this or - * the other CompletableFuture complete exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding the exception as its cause. + * Returns a new CompletableFuture that is completed + * when both this and the other given CompletableFuture complete, + * with the result of the given function of the results of the two + * CompletableFutures. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied function throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param fn the function to use to compute the value of * the returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture thenCombine(CompletableFuture other, - BiFun fn) { - return doThenBiApply(other, fn, null); + public CompletableFuture thenCombine + (CompletableFuture other, + BiFun fn) { + return doThenCombine(other, fn, null); } /** - * Creates and returns a CompletableFuture that is asynchronously - * completed using the {@link ForkJoinPool#commonPool()} with - * the result of the given function of this and the other given - * CompletableFuture's results when both complete. If this or - * the other CompletableFuture complete exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding the exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when both this and the other given CompletableFuture complete, + * with the result of the given function of the results of the two + * CompletableFutures from a task running in the + * {@link ForkJoinPool#commonPool()}. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied function throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param fn the function to use to compute the value of * the returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture thenCombineAsync(CompletableFuture other, - BiFun fn) { - return doThenBiApply(other, fn, ForkJoinPool.commonPool()); + public CompletableFuture thenCombineAsync + (CompletableFuture other, + BiFun fn) { + return doThenCombine(other, fn, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is - * asynchronously completed using the given executor with the - * result of the given function of this and the other given - * CompletableFuture's results when both complete. If this or - * the other CompletableFuture complete exceptionally, then the - * returned CompletableFuture also does so, with a - * CompletionException holding the exception as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when both this and the other given CompletableFuture complete, + * with the result of the given function of the results of the two + * CompletableFutures from a task running in the given executor. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied function throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param fn the function to use to compute the value of @@ -1788,22 +1997,24 @@ public class CompletableFuture implem * @param executor the executor to use for asynchronous execution * @return the new CompletableFuture */ - public CompletableFuture thenCombineAsync(CompletableFuture other, - BiFun fn, - Executor executor) { + public CompletableFuture thenCombineAsync + (CompletableFuture other, + BiFun fn, + Executor executor) { if (executor == null) throw new NullPointerException(); - return doThenBiApply(other, fn, executor); + return doThenCombine(other, fn, executor); } - private CompletableFuture doThenBiApply(CompletableFuture other, - BiFun fn, - Executor e) { + private CompletableFuture doThenCombine + (CompletableFuture other, + BiFun fn, + Executor e) { if (other == null || fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - BiApplyCompletion d = null; + ThenCombine d = null; Object r, s = null; if ((r = result) == null || (s = other.result) == null) { - d = new BiApplyCompletion(this, other, fn, dst, e); + d = new ThenCombine(this, other, fn, dst, e); CompletionNode q = null, p = new CompletionNode(d); while ((r == null && (r = result) == null) || (s == null && (s = other.result) == null)) { @@ -1847,7 +2058,7 @@ public class CompletableFuture implem if (ex == null) { try { if (e != null) - e.execute(new AsyncBiApply(t, u, fn, dst)); + e.execute(new AsyncCombine(t, u, fn, dst)); else v = fn.apply(t, u); } catch (Throwable rex) { @@ -1863,50 +2074,60 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed with - * the results of this and the other given CompletableFuture if - * both complete. If this and/or the other CompletableFuture - * complete exceptionally, then the returned CompletableFuture - * also does so, with a CompletionException holding one of these - * exceptions as its cause. + * Returns a new CompletableFuture that is completed + * when both this and the other given CompletableFuture complete, + * after performing the given action with the results of the two + * CompletableFutures. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied action throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param block the action to perform before completing the * returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture thenAcceptBoth(CompletableFuture other, - BiAction block) { - return doThenBiAccept(other, block, null); + public CompletableFuture thenAcceptBoth + (CompletableFuture other, + BiAction block) { + return doThenAcceptBoth(other, block, null); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the {@link ForkJoinPool#commonPool()} with - * the results of this and the other given CompletableFuture when - * both complete. If this and/or the other CompletableFuture - * complete exceptionally, then the returned CompletableFuture - * also does so, with a CompletionException holding one of these - * exceptions as its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when both this and the other given CompletableFuture complete, + * after performing the given action with the results of the two + * CompletableFutures from a task running in the {@link + * ForkJoinPool#commonPool()}. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied action throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param block the action to perform before completing the * returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture thenAcceptBothAsync(CompletableFuture other, - BiAction block) { - return doThenBiAccept(other, block, ForkJoinPool.commonPool()); + public CompletableFuture thenAcceptBothAsync + (CompletableFuture other, + BiAction block) { + return doThenAcceptBoth(other, block, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the given executor with the results of - * this and the other given CompletableFuture when both complete. - * If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture also does - * so, with a CompletionException holding one of these exceptions as - * its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when both this and the other given CompletableFuture complete, + * after performing the given action with the results of the two + * CompletableFutures from a task running in the given executor. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied action throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param block the action to perform before completing the @@ -1914,22 +2135,24 @@ public class CompletableFuture implem * @param executor the executor to use for asynchronous execution * @return the new CompletableFuture */ - public CompletableFuture thenAcceptBothAsync(CompletableFuture other, - BiAction block, - Executor executor) { + public CompletableFuture thenAcceptBothAsync + (CompletableFuture other, + BiAction block, + Executor executor) { if (executor == null) throw new NullPointerException(); - return doThenBiAccept(other, block, executor); + return doThenAcceptBoth(other, block, executor); } - private CompletableFuture doThenBiAccept(CompletableFuture other, - BiAction fn, - Executor e) { + private CompletableFuture doThenAcceptBoth + (CompletableFuture other, + BiAction fn, + Executor e) { if (other == null || fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - BiAcceptCompletion d = null; + ThenAcceptBoth d = null; Object r, s = null; if ((r = result) == null || (s = other.result) == null) { - d = new BiAcceptCompletion(this, other, fn, dst, e); + d = new ThenAcceptBoth(this, other, fn, dst, e); CompletionNode q = null, p = new CompletionNode(d); while ((r == null && (r = result) == null) || (s == null && (s = other.result) == null)) { @@ -1972,7 +2195,7 @@ public class CompletableFuture implem if (ex == null) { try { if (e != null) - e.execute(new AsyncBiAccept(t, u, fn, dst)); + e.execute(new AsyncAcceptBoth(t, u, fn, dst)); else fn.accept(t, u); } catch (Throwable rex) { @@ -1988,12 +2211,14 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed - * when this and the other given CompletableFuture both - * complete. If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture also does - * so, with a CompletionException holding one of these exceptions as - * its cause. + * Returns a new CompletableFuture that is completed + * when both this and the other given CompletableFuture complete, + * after performing the given action. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied action throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param action the action to perform before completing the @@ -2002,17 +2227,19 @@ public class CompletableFuture implem */ public CompletableFuture runAfterBoth(CompletableFuture other, Runnable action) { - return doThenBiRun(other, action, null); + return doRunAfterBoth(other, action, null); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the {@link ForkJoinPool#commonPool()} - * when this and the other given CompletableFuture both - * complete. If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture also does - * so, with a CompletionException holding one of these exceptions as - * its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when both this and the other given CompletableFuture complete, + * after performing the given action from a task running in the + * {@link ForkJoinPool#commonPool()}. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied action throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param action the action to perform before completing the @@ -2021,17 +2248,19 @@ public class CompletableFuture implem */ public CompletableFuture runAfterBothAsync(CompletableFuture other, Runnable action) { - return doThenBiRun(other, action, ForkJoinPool.commonPool()); + return doRunAfterBoth(other, action, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the given executor - * when this and the other given CompletableFuture both - * complete. If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture also does - * so, with a CompletionException holding one of these exceptions as - * its cause. + * Returns a new CompletableFuture that is asynchronously completed + * when both this and the other given CompletableFuture complete, + * after performing the given action from a task running in the + * given executor. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, or the supplied action throws an exception, + * then the returned CompletableFuture completes exceptionally + * with a CompletionException holding the exception as its cause. * * @param other the other CompletableFuture * @param action the action to perform before completing the @@ -2043,18 +2272,18 @@ public class CompletableFuture implem Runnable action, Executor executor) { if (executor == null) throw new NullPointerException(); - return doThenBiRun(other, action, executor); + return doRunAfterBoth(other, action, executor); } - private CompletableFuture doThenBiRun(CompletableFuture other, - Runnable action, - Executor e) { + private CompletableFuture doRunAfterBoth(CompletableFuture other, + Runnable action, + Executor e) { if (other == null || action == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - BiRunCompletion d = null; + RunAfterBoth d = null; Object r, s = null; if ((r = result) == null || (s = other.result) == null) { - d = new BiRunCompletion(this, other, action, dst, e); + d = new RunAfterBoth(this, other, action, dst, e); CompletionNode q = null, p = new CompletionNode(d); while ((r == null && (r = result) == null) || (s == null && (s = other.result) == null)) { @@ -2100,56 +2329,73 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed with - * the result of the given function of either this or the other - * given CompletableFuture's results when either complete. If - * this and/or the other CompletableFuture complete exceptionally, - * then the returned CompletableFuture may also do so, with a - * CompletionException holding one of these exceptions as its cause. - * No guarantees are made about which result or exception is used - * in the returned CompletableFuture. + * Returns a new CompletableFuture that is completed + * when either this or the other given CompletableFuture completes, + * with the result of the given function of either this or the other + * CompletableFuture's result. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied function + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param fn the function to use to compute the value of * the returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture applyToEither(CompletableFuture other, - Fun fn) { - return doOrApply(other, fn, null); + public CompletableFuture applyToEither + (CompletableFuture other, + Fun fn) { + return doApplyToEither(other, fn, null); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the {@link ForkJoinPool#commonPool()} with - * the result of the given function of either this or the other - * given CompletableFuture's results when either complete. If - * this and/or the other CompletableFuture complete exceptionally, - * then the returned CompletableFuture may also do so, with a - * CompletionException holding one of these exceptions as its cause. - * No guarantees are made about which result or exception is used - * in the returned CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * when either this or the other given CompletableFuture completes, + * with the result of the given function of either this or the other + * CompletableFuture's result from a task running in the + * {@link ForkJoinPool#commonPool()}. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied function + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param fn the function to use to compute the value of * the returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture applyToEitherAsync(CompletableFuture other, - Fun fn) { - return doOrApply(other, fn, ForkJoinPool.commonPool()); + public CompletableFuture applyToEitherAsync + (CompletableFuture other, + Fun fn) { + return doApplyToEither(other, fn, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the given executor with the result of the - * given function of either this or the other given - * CompletableFuture's results when either complete. If this - * and/or the other CompletableFuture complete exceptionally, then - * the returned CompletableFuture may also do so, with a - * CompletionException holding one of these exceptions as its cause. - * No guarantees are made about which result or exception is used - * in the returned CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * when either this or the other given CompletableFuture completes, + * with the result of the given function of either this or the other + * CompletableFuture's result from a task running in the + * given executor. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied function + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param fn the function to use to compute the value of @@ -2157,22 +2403,24 @@ public class CompletableFuture implem * @param executor the executor to use for asynchronous execution * @return the new CompletableFuture */ - public CompletableFuture applyToEitherAsync(CompletableFuture other, - Fun fn, - Executor executor) { + public CompletableFuture applyToEitherAsync + (CompletableFuture other, + Fun fn, + Executor executor) { if (executor == null) throw new NullPointerException(); - return doOrApply(other, fn, executor); + return doApplyToEither(other, fn, executor); } - private CompletableFuture doOrApply(CompletableFuture other, - Fun fn, - Executor e) { + private CompletableFuture doApplyToEither + (CompletableFuture other, + Fun fn, + Executor e) { if (other == null || fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - OrApplyCompletion d = null; + ApplyToEither d = null; Object r; if ((r = result) == null && (r = other.result) == null) { - d = new OrApplyCompletion(this, other, fn, dst, e); + d = new ApplyToEither(this, other, fn, dst, e); CompletionNode q = null, p = new CompletionNode(d); while ((r = result) == null && (r = other.result) == null) { if (q != null) { @@ -2216,56 +2464,73 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed after - * performing the given action with the result of either this or the - * other given CompletableFuture's result, when either complete. - * If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do - * so, with a CompletionException holding one of these exceptions as - * its cause. No guarantees are made about which exception is - * used in the returned CompletableFuture. + * Returns a new CompletableFuture that is completed + * when either this or the other given CompletableFuture completes, + * after performing the given action with the result of either this + * or the other CompletableFuture's result. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied action + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param block the action to perform before completing the * returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture acceptEither(CompletableFuture other, - Action block) { - return doOrAccept(other, block, null); + public CompletableFuture acceptEither + (CompletableFuture other, + Action block) { + return doAcceptEither(other, block, null); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the {@link ForkJoinPool#commonPool()}, - * performing the given action with the result of either this or - * the other given CompletableFuture's result, when either - * complete. If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do - * so, with a CompletionException holding one of these exceptions as - * its cause. No guarantees are made about which exception is - * used in the returned CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * when either this or the other given CompletableFuture completes, + * after performing the given action with the result of either this + * or the other CompletableFuture's result from a task running in + * the {@link ForkJoinPool#commonPool()}. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied action + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param block the action to perform before completing the * returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture acceptEitherAsync(CompletableFuture other, - Action block) { - return doOrAccept(other, block, ForkJoinPool.commonPool()); + public CompletableFuture acceptEitherAsync + (CompletableFuture other, + Action block) { + return doAcceptEither(other, block, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the given executor, - * performing the given action with the result of either this or - * the other given CompletableFuture's result, when either - * complete. If this and/or the other CompletableFuture complete - * exceptionally, then the returned CompletableFuture may also do - * so, with a CompletionException holding one of these exceptions as - * its cause. No guarantees are made about which exception is - * used in the returned CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * when either this or the other given CompletableFuture completes, + * after performing the given action with the result of either this + * or the other CompletableFuture's result from a task running in + * the given executor. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied action + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param block the action to perform before completing the @@ -2273,22 +2538,24 @@ public class CompletableFuture implem * @param executor the executor to use for asynchronous execution * @return the new CompletableFuture */ - public CompletableFuture acceptEitherAsync(CompletableFuture other, - Action block, - Executor executor) { + public CompletableFuture acceptEitherAsync + (CompletableFuture other, + Action block, + Executor executor) { if (executor == null) throw new NullPointerException(); - return doOrAccept(other, block, executor); + return doAcceptEither(other, block, executor); } - private CompletableFuture doOrAccept(CompletableFuture other, - Action fn, - Executor e) { + private CompletableFuture doAcceptEither + (CompletableFuture other, + Action fn, + Executor e) { if (other == null || fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - OrAcceptCompletion d = null; + AcceptEither d = null; Object r; if ((r = result) == null && (r = other.result) == null) { - d = new OrAcceptCompletion(this, other, fn, dst, e); + d = new AcceptEither(this, other, fn, dst, e); CompletionNode q = null, p = new CompletionNode(d); while ((r = result) == null && (r = other.result) == null) { if (q != null) { @@ -2331,13 +2598,18 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed - * after this or the other given CompletableFuture complete. If - * this and/or the other CompletableFuture complete exceptionally, - * then the returned CompletableFuture may also do so, with a - * CompletionException holding one of these exceptions as its cause. - * No guarantees are made about which exception is used in the - * returned CompletableFuture. + * Returns a new CompletableFuture that is completed + * when either this or the other given CompletableFuture completes, + * after performing the given action. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied action + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param action the action to perform before completing the @@ -2346,38 +2618,49 @@ public class CompletableFuture implem */ public CompletableFuture runAfterEither(CompletableFuture other, Runnable action) { - return doOrRun(other, action, null); + return doRunAfterEither(other, action, null); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the {@link ForkJoinPool#commonPool()} - * after this or the other given CompletableFuture complete. If - * this and/or the other CompletableFuture complete exceptionally, - * then the returned CompletableFuture may also do so, with a - * CompletionException holding one of these exceptions as its cause. - * No guarantees are made about which exception is used in the - * returned CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * when either this or the other given CompletableFuture completes, + * after performing the given action from a task running in the + * {@link ForkJoinPool#commonPool()}. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied action + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param action the action to perform before completing the * returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture runAfterEitherAsync(CompletableFuture other, - Runnable action) { - return doOrRun(other, action, ForkJoinPool.commonPool()); + public CompletableFuture runAfterEitherAsync + (CompletableFuture other, + Runnable action) { + return doRunAfterEither(other, action, ForkJoinPool.commonPool()); } /** - * Creates and returns a CompletableFuture that is completed - * asynchronously using the given executor after this or the other - * given CompletableFuture complete. If this and/or the other - * CompletableFuture complete exceptionally, then the returned - * CompletableFuture may also do so, with a CompletionException - * holding one of these exceptions as its cause. No guarantees are - * made about which exception is used in the returned - * CompletableFuture. + * Returns a new CompletableFuture that is asynchronously completed + * when either this or the other given CompletableFuture completes, + * after performing the given action from a task running in the + * given executor. + * + *

If this and/or the other CompletableFuture complete + * exceptionally, then the returned CompletableFuture may also do so, + * with a CompletionException holding one of these exceptions as its + * cause. No guarantees are made about which result or exception is + * used in the returned CompletableFuture. If the supplied action + * throws an exception, then the returned CompletableFuture completes + * exceptionally with a CompletionException holding the exception as + * its cause. * * @param other the other CompletableFuture * @param action the action to perform before completing the @@ -2385,22 +2668,24 @@ public class CompletableFuture implem * @param executor the executor to use for asynchronous execution * @return the new CompletableFuture */ - public CompletableFuture runAfterEitherAsync(CompletableFuture other, - Runnable action, - Executor executor) { + public CompletableFuture runAfterEitherAsync + (CompletableFuture other, + Runnable action, + Executor executor) { if (executor == null) throw new NullPointerException(); - return doOrRun(other, action, executor); + return doRunAfterEither(other, action, executor); } - private CompletableFuture doOrRun(CompletableFuture other, - Runnable action, - Executor e) { + private CompletableFuture doRunAfterEither + (CompletableFuture other, + Runnable action, + Executor e) { if (other == null || action == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); - OrRunCompletion d = null; + RunAfterEither d = null; Object r; if ((r = result) == null && (r = other.result) == null) { - d = new OrRunCompletion(this, other, action, dst, e); + d = new RunAfterEither(this, other, action, dst, e); CompletionNode q = null, p = new CompletionNode(d); while ((r = result) == null && (r = other.result) == null) { if (q != null) { @@ -2438,27 +2723,77 @@ public class CompletableFuture implem } /** - * Returns a CompletableFuture (or an equivalent one) produced by - * the given function of the result of this CompletableFuture when - * completed. If this CompletableFuture completes exceptionally, - * then the returned CompletableFuture also does so, with a + * Returns a CompletableFuture that upon completion, has the same + * value as produced by the given function of the result of this + * CompletableFuture. + * + *

If this CompletableFuture completes exceptionally, then the + * returned CompletableFuture also does so, with a * CompletionException holding this exception as its cause. + * Similarly, if the computed CompletableFuture completes + * exceptionally, then so does the returned CompletableFuture. * * @param fn the function returning a new CompletableFuture - * @return the CompletableFuture, that {@code isDone()} upon - * return if completed by the given function, or an exception - * occurs + * @return the CompletableFuture + */ + public CompletableFuture thenCompose + (Fun> fn) { + return doThenCompose(fn, null); + } + + /** + * Returns a CompletableFuture that upon completion, has the same + * value as that produced asynchronously using the {@link + * ForkJoinPool#commonPool()} by the given function of the result + * of this CompletableFuture. + * + *

If this CompletableFuture completes exceptionally, then the + * returned CompletableFuture also does so, with a + * CompletionException holding this exception as its cause. + * Similarly, if the computed CompletableFuture completes + * exceptionally, then so does the returned CompletableFuture. + * + * @param fn the function returning a new CompletableFuture + * @return the CompletableFuture */ - public CompletableFuture thenCompose(Fun> fn) { + public CompletableFuture thenComposeAsync + (Fun> fn) { + return doThenCompose(fn, ForkJoinPool.commonPool()); + } + + /** + * Returns a CompletableFuture that upon completion, has the same + * value as that produced asynchronously using the given executor + * by the given function of this CompletableFuture. + * + *

If this CompletableFuture completes exceptionally, then the + * returned CompletableFuture also does so, with a + * CompletionException holding this exception as its cause. + * Similarly, if the computed CompletableFuture completes + * exceptionally, then so does the returned CompletableFuture. + * + * @param fn the function returning a new CompletableFuture + * @param executor the executor to use for asynchronous execution + * @return the CompletableFuture + */ + public CompletableFuture thenComposeAsync + (Fun> fn, + Executor executor) { + if (executor == null) throw new NullPointerException(); + return doThenCompose(fn, executor); + } + + private CompletableFuture doThenCompose + (Fun> fn, + Executor e) { if (fn == null) throw new NullPointerException(); CompletableFuture dst = null; - ComposeCompletion d = null; + ThenCompose d = null; Object r; if ((r = result) == null) { dst = new CompletableFuture(); CompletionNode p = new CompletionNode - (d = new ComposeCompletion(this, fn, dst)); + (d = new ThenCompose(this, fn, dst, e)); while ((r = result) == null) { if (UNSAFE.compareAndSwapObject (this, COMPLETIONS, p.next = completions, p)) @@ -2477,18 +2812,23 @@ public class CompletableFuture implem t = tr; } if (ex == null) { - try { - dst = fn.apply(t); - } catch (Throwable rex) { - ex = rex; + if (e != null) { + if (dst == null) + dst = new CompletableFuture(); + e.execute(new AsyncCompose(t, fn, dst)); + } + else { + try { + if ((dst = fn.apply(t)) == null) + ex = new NullPointerException(); + } catch (Throwable rex) { + ex = rex; + } } } - if (dst == null) { + if (dst == null) dst = new CompletableFuture(); - if (ex == null) - ex = new NullPointerException(); - } - if (ex != null) + if (e == null || ex != null) dst.internalComplete(null, ex); } helpPostComplete(); @@ -2497,19 +2837,20 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed with - * the result of the given function of the exception triggering - * this CompletableFuture's completion when it completes - * exceptionally; Otherwise, if this CompletableFuture completes - * normally, then the returned CompletableFuture also completes - * normally with the same value. + * Returns a new CompletableFuture that is completed when this + * CompletableFuture completes, with the result of the given + * function of the exception triggering this CompletableFuture's + * completion when it completes exceptionally; otherwise, if this + * CompletableFuture completes normally, then the returned + * CompletableFuture also completes normally with the same value. * * @param fn the function to use to compute the value of the * returned CompletableFuture if this CompletableFuture completed * exceptionally * @return the new CompletableFuture */ - public CompletableFuture exceptionally(Fun fn) { + public CompletableFuture exceptionally + (Fun fn) { if (fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); ExceptionCompletion d = null; @@ -2545,18 +2886,19 @@ public class CompletableFuture implem } /** - * Creates and returns a CompletableFuture that is completed with - * the result of the given function of the result and exception of - * this CompletableFuture's completion when it completes. The - * given function is invoked with the result (or {@code null} if - * none) and the exception (or {@code null} if none) of this - * CompletableFuture when complete. + * Returns a new CompletableFuture that is completed when this + * CompletableFuture completes, with the result of the given + * function of the result and exception of this CompletableFuture's + * completion. The given function is invoked with the result (or + * {@code null} if none) and the exception (or {@code null} if none) + * of this CompletableFuture when complete. * * @param fn the function to use to compute the value of the * returned CompletableFuture * @return the new CompletableFuture */ - public CompletableFuture handle(BiFun fn) { + public CompletableFuture handle + (BiFun fn) { if (fn == null) throw new NullPointerException(); CompletableFuture dst = new CompletableFuture(); HandleCompletion d = null; @@ -2595,9 +2937,230 @@ public class CompletableFuture implem return dst; } + + /* ------------- Arbitrary-arity constructions -------------- */ + + /* + * The basic plan of attack is to recursively form binary + * completion trees of elements. This can be overkill for small + * sets, but scales nicely. The And/All vs Or/Any forms use the + * same idea, but details differ. + */ + + /** + * Returns a new CompletableFuture that is completed when all of + * the given CompletableFutures complete. If any of the given + * CompletableFutures complete exceptionally, then the returned + * CompletableFuture also does so, with a CompletionException + * holding this exception as its cause. Otherwise, the results, + * if any, of the given CompletableFutures are not reflected in + * the returned CompletableFuture, but may be obtained by + * inspecting them individually. If no CompletableFutures are + * provided, returns a CompletableFuture completed with the value + * {@code null}. + * + *

Among the applications of this method is to await completion + * of a set of independent CompletableFutures before continuing a + * program, as in: {@code CompletableFuture.allOf(c1, c2, + * c3).join();}. + * + * @param cfs the CompletableFutures + * @return a new CompletableFuture that is completed when all of the + * given CompletableFutures complete + * @throws NullPointerException if the array or any of its elements are + * {@code null} + */ + public static CompletableFuture allOf(CompletableFuture... cfs) { + int len = cfs.length; // Directly handle empty and singleton cases + if (len > 1) + return allTree(cfs, 0, len - 1); + else { + CompletableFuture dst = new CompletableFuture(); + CompletableFuture f; + if (len == 0) + dst.result = NIL; + else if ((f = cfs[0]) == null) + throw new NullPointerException(); + else { + ThenPropagate d = null; + CompletionNode p = null; + Object r; + while ((r = f.result) == null) { + if (d == null) + d = new ThenPropagate(f, dst); + else if (p == null) + p = new CompletionNode(d); + else if (UNSAFE.compareAndSwapObject + (f, COMPLETIONS, p.next = f.completions, p)) + break; + } + if (r != null && (d == null || d.compareAndSet(0, 1))) + dst.internalComplete(null, (r instanceof AltResult) ? + ((AltResult)r).ex : null); + f.helpPostComplete(); + } + return dst; + } + } + + /** + * Recursively constructs an And'ed tree of CompletableFutures. + * Called only when array known to have at least two elements. + */ + private static CompletableFuture allTree(CompletableFuture[] cfs, + int lo, int hi) { + CompletableFuture fst, snd; + int mid = (lo + hi) >>> 1; + if ((fst = (lo == mid ? cfs[lo] : allTree(cfs, lo, mid))) == null || + (snd = (hi == mid+1 ? cfs[hi] : allTree(cfs, mid+1, hi))) == null) + throw new NullPointerException(); + CompletableFuture dst = new CompletableFuture(); + AndCompletion d = null; + CompletionNode p = null, q = null; + Object r = null, s = null; + while ((r = fst.result) == null || (s = snd.result) == null) { + if (d == null) + d = new AndCompletion(fst, snd, dst); + else if (p == null) + p = new CompletionNode(d); + else if (q == null) { + if (UNSAFE.compareAndSwapObject + (fst, COMPLETIONS, p.next = fst.completions, p)) + q = new CompletionNode(d); + } + else if (UNSAFE.compareAndSwapObject + (snd, COMPLETIONS, q.next = snd.completions, q)) + break; + } + if ((r != null || (r = fst.result) != null) && + (s != null || (s = snd.result) != null) && + (d == null || d.compareAndSet(0, 1))) { + Throwable ex; + if (r instanceof AltResult) + ex = ((AltResult)r).ex; + else + ex = null; + if (ex == null && (s instanceof AltResult)) + ex = ((AltResult)s).ex; + dst.internalComplete(null, ex); + } + fst.helpPostComplete(); + snd.helpPostComplete(); + return dst; + } + /** - * Attempts to complete this CompletableFuture with - * a {@link CancellationException}. + * Returns a new CompletableFuture that is completed when any of + * the given CompletableFutures complete, with the same result. + * Otherwise, if it completed exceptionally, the returned + * CompletableFuture also does so, with a CompletionException + * holding this exception as its cause. If no CompletableFutures + * are provided, returns an incomplete CompletableFuture. + * + * @param cfs the CompletableFutures + * @return a new CompletableFuture that is completed with the + * result or exception of any of the given CompletableFutures when + * one completes + * @throws NullPointerException if the array or any of its elements are + * {@code null} + */ + public static CompletableFuture anyOf(CompletableFuture... cfs) { + int len = cfs.length; // Same idea as allOf + if (len > 1) + return anyTree(cfs, 0, len - 1); + else { + CompletableFuture dst = new CompletableFuture(); + CompletableFuture f; + if (len == 0) + ; // skip + else if ((f = cfs[0]) == null) + throw new NullPointerException(); + else { + ThenCopy d = null; + CompletionNode p = null; + Object r; + while ((r = f.result) == null) { + if (d == null) + d = new ThenCopy(f, dst); + else if (p == null) + p = new CompletionNode(d); + else if (UNSAFE.compareAndSwapObject + (f, COMPLETIONS, p.next = f.completions, p)) + break; + } + if (r != null && (d == null || d.compareAndSet(0, 1))) { + Throwable ex; Object t; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + t = r; + } + dst.internalComplete(t, ex); + } + f.helpPostComplete(); + } + return dst; + } + } + + /** + * Recursively constructs an Or'ed tree of CompletableFutures. + */ + private static CompletableFuture anyTree(CompletableFuture[] cfs, + int lo, int hi) { + CompletableFuture fst, snd; + int mid = (lo + hi) >>> 1; + if ((fst = (lo == mid ? cfs[lo] : anyTree(cfs, lo, mid))) == null || + (snd = (hi == mid+1 ? cfs[hi] : anyTree(cfs, mid+1, hi))) == null) + throw new NullPointerException(); + CompletableFuture dst = new CompletableFuture(); + OrCompletion d = null; + CompletionNode p = null, q = null; + Object r; + while ((r = fst.result) == null && (r = snd.result) == null) { + if (d == null) + d = new OrCompletion(fst, snd, dst); + else if (p == null) + p = new CompletionNode(d); + else if (q == null) { + if (UNSAFE.compareAndSwapObject + (fst, COMPLETIONS, p.next = fst.completions, p)) + q = new CompletionNode(d); + } + else if (UNSAFE.compareAndSwapObject + (snd, COMPLETIONS, q.next = snd.completions, q)) + break; + } + if ((r != null || (r = fst.result) != null || + (r = snd.result) != null) && + (d == null || d.compareAndSet(0, 1))) { + Throwable ex; Object t; + if (r instanceof AltResult) { + ex = ((AltResult)r).ex; + t = null; + } + else { + ex = null; + t = r; + } + dst.internalComplete(t, ex); + } + fst.helpPostComplete(); + snd.helpPostComplete(); + return dst; + } + + /* ------------- Control and status methods -------------- */ + + /** + * If not already completed, completes this CompletableFuture with + * a {@link CancellationException}. Dependent CompletableFutures + * that have not already completed will also complete + * exceptionally, with a {@link CompletionException} caused by + * this {@code CancellationException}. * * @param mayInterruptIfRunning this value has no effect in this * implementation because interrupts are not used to control @@ -2606,16 +3169,11 @@ public class CompletableFuture implem * @return {@code true} if this task is now cancelled */ public boolean cancel(boolean mayInterruptIfRunning) { - Object r; - while ((r = result) == null) { - r = new AltResult(new CancellationException()); - if (UNSAFE.compareAndSwapObject(this, RESULT, null, r)) { - postComplete(); - return true; - } - } - return ((r instanceof AltResult) && - (((AltResult)r).ex instanceof CancellationException)); + boolean cancelled = (result == null) && + UNSAFE.compareAndSwapObject + (this, RESULT, null, new AltResult(new CancellationException())); + postComplete(); + return cancelled || isCancelled(); } /** @@ -2662,6 +3220,44 @@ public class CompletableFuture implem postComplete(); } + /** + * Returns the estimated number of CompletableFutures whose + * completions are awaiting completion of this CompletableFuture. + * This method is designed for use in monitoring system state, not + * for synchronization control. + * + * @return the number of dependent CompletableFutures + */ + public int getNumberOfDependents() { + int count = 0; + for (CompletionNode p = completions; p != null; p = p.next) + ++count; + return count; + } + + /** + * Returns a string identifying this CompletableFuture, as well as + * its completion state. The state, in brackets, contains the + * String {@code "Completed Normally"} or the String {@code + * "Completed Exceptionally"}, or the String {@code "Not + * completed"} followed by the number of CompletableFutures + * dependent upon its completion, if any. + * + * @return a string identifying this CompletableFuture, as well as its state + */ + public String toString() { + Object r = result; + int count; + return super.toString() + + ((r == null) ? + (((count = getNumberOfDependents()) == 0) ? + "[Not completed]" : + "[Not completed, " + count + " dependents]") : + (((r instanceof AltResult) && ((AltResult)r).ex != null) ? + "[Completed exceptionally]" : + "[Completed normally]")); + } + // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long RESULT; @@ -2682,7 +3278,6 @@ public class CompletableFuture implem } } - /** * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. * Replace with a simple call to Unsafe.getUnsafe when integrating