--- old/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java 2018-09-28 08:01:19.312714211 -0700 +++ new/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java 2018-09-28 08:01:18.740714409 -0700 @@ -957,17 +957,17 @@ @SuppressWarnings("serial") static final class UniExceptionally extends UniCompletion { Function fn; - UniExceptionally(CompletableFuture dep, CompletableFuture src, + UniExceptionally(Executor executor, + CompletableFuture dep, CompletableFuture src, Function fn) { - super(null, dep, src); this.fn = fn; + super(executor, dep, src); this.fn = fn; } - final CompletableFuture tryFire(int mode) { // never ASYNC - // assert mode != ASYNC; + final CompletableFuture tryFire(int mode) { CompletableFuture d; CompletableFuture a; Object r; Function f; if ((d = dep) == null || (f = fn) == null || (a = src) == null || (r = a.result) == null - || !d.uniExceptionally(r, f, this)) + || !d.uniExceptionally(r, f, mode > 0 ? null : this)) return null; dep = null; src = null; fn = null; return d.postFire(a, mode); @@ -980,11 +980,11 @@ Throwable x; if (result == null) { try { - if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) { - if (c != null && !c.claim()) - return false; + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) completeValue(f.apply(x)); - } else + else internalComplete(r); } catch (Throwable ex) { completeThrowable(ex); @@ -994,14 +994,88 @@ } private CompletableFuture uniExceptionallyStage( - Function f) { + Executor e, Function f) { if (f == null) throw new NullPointerException(); CompletableFuture d = newIncompleteFuture(); Object r; if ((r = result) == null) - unipush(new UniExceptionally(d, this, f)); - else + unipush(new UniExceptionally(e, d, this, f)); + else if (e == null) d.uniExceptionally(r, f, null); + else { + try { + e.execute(new UniExceptionally(null, d, this, f)); + } catch (Throwable ex) { + d.result = encodeThrowable(ex); + } + } + return d; + } + + @SuppressWarnings("serial") + static final class UniComposeExceptionally extends UniCompletion { + Function> fn; + UniComposeExceptionally(Executor executor, CompletableFuture dep, + CompletableFuture src, + Function> fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + Function> f; + Object r; Throwable x; + if ((d = dep) == null || (f = fn) == null + || (a = src) == null || (r = a.result) == null) + return null; + if (d.result == null) { + if ((r instanceof AltResult) && + (x = ((AltResult)r).ex) != null) { + try { + if (mode <= 0 && !claim()) + return null; + CompletableFuture g = f.apply(x).toCompletableFuture(); + if ((r = g.result) != null) + d.completeRelay(r); + else { + g.unipush(new UniRelay(d, g)); + if (d.result == null) + return null; + } + } catch (Throwable ex) { + d.completeThrowable(ex); + } + } + else + d.internalComplete(r); + } + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + private CompletableFuture uniComposeExceptionallyStage( + Executor e, Function> f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = newIncompleteFuture(); + Object r, s; Throwable x; + if ((r = result) == null) + unipush(new UniComposeExceptionally(e, d, this, f)); + else if (!(r instanceof AltResult) || (x = ((AltResult)r).ex) == null) + d.internalComplete(r); + else + try { + if (e != null) + e.execute(new UniComposeExceptionally(null, d, this, f)); + else { + CompletableFuture g = f.apply(x).toCompletableFuture(); + if ((s = g.result) != null) + d.result = encodeRelay(s); + else + g.unipush(new UniRelay(d, g)); + } + } catch (Throwable ex) { + d.result = encodeThrowable(ex); + } return d; } @@ -1093,7 +1167,7 @@ Object r, s; Throwable x; if ((r = result) == null) unipush(new UniCompose(e, d, this, f)); - else if (e == null) { + else { if (r instanceof AltResult) { if ((x = ((AltResult)r).ex) != null) { d.result = encodeThrowable(x, r); @@ -1102,23 +1176,20 @@ r = null; } try { - @SuppressWarnings("unchecked") T t = (T) r; - CompletableFuture g = f.apply(t).toCompletableFuture(); - if ((s = g.result) != null) - d.result = encodeRelay(s); + if (e != null) + e.execute(new UniCompose(null, d, this, f)); else { - g.unipush(new UniRelay(d, g)); + @SuppressWarnings("unchecked") T t = (T) r; + CompletableFuture g = f.apply(t).toCompletableFuture(); + if ((s = g.result) != null) + d.result = encodeRelay(s); + else + g.unipush(new UniRelay(d, g)); } } catch (Throwable ex) { d.result = encodeThrowable(ex); } } - else - try { - e.execute(new UniCompose(null, d, this, f)); - } catch (Throwable ex) { - d.result = encodeThrowable(ex); - } return d; } @@ -1898,7 +1969,7 @@ * Creates a new complete CompletableFuture with given encoded result. */ CompletableFuture(Object r) { - this.result = r; + RESULT.setRelease(this, r); } /** @@ -2285,28 +2356,36 @@ return this; } - // not in interface CompletionStage - - /** - * 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. - * Note: More flexible versions of this functionality are - * available using methods {@code whenComplete} and {@code handle}. - * - * @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( Function fn) { - return uniExceptionallyStage(fn); + return uniExceptionallyStage(null, fn); } + public CompletableFuture exceptionallyAsync( + Function fn) { + return uniExceptionallyStage(defaultExecutor(), fn); + } + + public CompletableFuture exceptionallyAsync( + Function fn, Executor executor) { + return uniExceptionallyStage(screenExecutor(executor), fn); + } + + public CompletableFuture exceptionallyCompose( + Function> fn) { + return uniComposeExceptionallyStage(null, fn); + } + + public CompletableFuture exceptionallyComposeAsync( + Function> fn) { + return uniComposeExceptionallyStage(defaultExecutor(), fn); + } + + public CompletableFuture exceptionallyComposeAsync( + Function> fn, + Executor executor) { + return uniComposeExceptionallyStage(screenExecutor(executor), fn); + } /* ------------- Arbitrary-arity constructions -------------- */