5 |
|
*/ |
6 |
|
|
7 |
|
package java.util.concurrent; |
8 |
– |
import java.util.function.Block; |
8 |
|
import java.util.function.Supplier; |
9 |
|
import java.util.function.Function; |
10 |
|
import java.util.function.BiFunction; |
658 |
|
} |
659 |
|
|
660 |
|
/** |
661 |
< |
* Creates and returns a CompletableFuture that is completed after |
662 |
< |
* performing the given action with the exception triggering this |
663 |
< |
* CompletableFuture's completion if/when it completes |
664 |
< |
* exceptionally. |
665 |
< |
* |
666 |
< |
* @param action the action to perform before completing the |
667 |
< |
* returned CompletableFuture |
661 |
> |
* Creates and returns a CompletableFuture that is completed with |
662 |
> |
* the result of the given function of the exception triggering |
663 |
> |
* this CompletableFuture's completion if/when it completes |
664 |
> |
* exceptionally; Otherwise, if this CompletableFuture completes |
665 |
> |
* normally, then the returned CompletableFuture also completes |
666 |
> |
* normally with the same value. |
667 |
> |
* |
668 |
> |
* @param fn the function to use to compute the value of the |
669 |
> |
* returned CompletableFuture if this CompletableFuture completed |
670 |
> |
* exceptionally |
671 |
|
* @return the new CompletableFuture |
672 |
|
*/ |
673 |
< |
public CompletableFuture<Void> exceptionally(Block<Throwable> action) { |
674 |
< |
if (action == null) throw new NullPointerException(); |
675 |
< |
CompletableFuture<Void> dst = new CompletableFuture<Void>(); |
673 |
> |
public CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn) { |
674 |
> |
if (fn == null) throw new NullPointerException(); |
675 |
> |
CompletableFuture<T> dst = new CompletableFuture<T>(); |
676 |
|
ExceptionAction<T> d = null; |
677 |
< |
Object r; Throwable ex; |
677 |
> |
Object r; |
678 |
|
if ((r = result) == null) { |
679 |
|
CompletionNode p = |
680 |
< |
new CompletionNode(d = new ExceptionAction<T>(this, action, dst)); |
680 |
> |
new CompletionNode(d = new ExceptionAction<T>(this, fn, dst)); |
681 |
|
while ((r = result) == null) { |
682 |
|
if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, |
683 |
|
p.next = completions, p)) |
684 |
|
break; |
685 |
|
} |
686 |
|
} |
687 |
< |
if (r != null && (d == null || d.compareAndSet(0, 1)) && |
688 |
< |
(r instanceof AltResult) && (ex = ((AltResult)r).ex) != null) { |
689 |
< |
try { |
690 |
< |
action.accept(ex); |
691 |
< |
dst.complete(null); |
692 |
< |
} catch (Throwable rex) { |
693 |
< |
dst.completeExceptionally(rex); |
687 |
> |
if (r != null && (d == null || d.compareAndSet(0, 1))) { |
688 |
> |
T t; Throwable ex = null; |
689 |
> |
if (r instanceof AltResult) { |
690 |
> |
if ((ex = ((AltResult)r).ex) != null) { |
691 |
> |
try { |
692 |
> |
dst.complete(fn.apply(ex)); |
693 |
> |
} catch (Throwable rex) { |
694 |
> |
dst.completeExceptionally(rex); |
695 |
> |
} |
696 |
> |
} |
697 |
> |
t = null; |
698 |
|
} |
699 |
+ |
else |
700 |
+ |
t = (T) r; |
701 |
+ |
if (ex == null) |
702 |
+ |
dst.complete(t); |
703 |
|
} |
704 |
|
if (r != null) |
705 |
|
postComplete(); |
744 |
|
} |
745 |
|
|
746 |
|
/** |
747 |
< |
* Whether or not already completed, sets the value subsequently |
748 |
< |
* returned by method get() and related methods to the given |
749 |
< |
* value. This method is designed for use in error recovery |
750 |
< |
* actions, and is very unlikely to be useful otherwise. |
747 |
> |
* Forcibly sets or resets the value subsequently returned by |
748 |
> |
* method get() and related methods, whether or not already |
749 |
> |
* completed. This method is designed for use only in error |
750 |
> |
* recovery actions, and even in such situations may result in |
751 |
> |
* ongoing dependent completions using established versus |
752 |
> |
* overwritten values. |
753 |
|
* |
754 |
|
* @param value the completion value |
755 |
|
*/ |
756 |
< |
public void force(T value) { |
756 |
> |
public void obtrudeValue(T value) { |
757 |
|
result = (value == null) ? NIL : value; |
758 |
|
postComplete(); |
759 |
|
} |
1302 |
|
|
1303 |
|
static final class ExceptionAction<T> extends Completion { |
1304 |
|
final CompletableFuture<? extends T> src; |
1305 |
< |
final Block<? super Throwable> fn; |
1306 |
< |
final CompletableFuture<Void> dst; |
1305 |
> |
final Function<? super Throwable, ? extends T> fn; |
1306 |
> |
final CompletableFuture<T> dst; |
1307 |
|
ExceptionAction(CompletableFuture<? extends T> src, |
1308 |
< |
Block<? super Throwable> fn, |
1309 |
< |
CompletableFuture<Void> dst) { |
1308 |
> |
Function<? super Throwable, ? extends T> fn, |
1309 |
> |
CompletableFuture<T> dst) { |
1310 |
|
this.src = src; this.fn = fn; this.dst = dst; |
1311 |
|
} |
1312 |
|
public void run() { |
1313 |
|
CompletableFuture<? extends T> a; |
1314 |
< |
Block<? super Throwable> fn; |
1315 |
< |
CompletableFuture<Void> dst; |
1316 |
< |
Object r; Throwable ex; |
1314 |
> |
Function<? super Throwable, ? extends T> fn; |
1315 |
> |
CompletableFuture<T> dst; |
1316 |
> |
Object r; T t; Throwable ex; |
1317 |
|
if ((dst = this.dst) != null && |
1318 |
|
(fn = this.fn) != null && |
1319 |
|
(a = this.src) != null && |
1320 |
|
(r = a.result) != null && |
1321 |
|
compareAndSet(0, 1)) { |
1322 |
< |
if ((r instanceof AltResult) && |
1323 |
< |
(ex = ((AltResult)r).ex) != null) { |
1324 |
< |
try { |
1325 |
< |
fn.accept(ex); |
1326 |
< |
dst.complete(null); |
1327 |
< |
} catch (Throwable rex) { |
1328 |
< |
dst.completeExceptionally(rex); |
1322 |
> |
if (r instanceof AltResult) { |
1323 |
> |
if ((ex = ((AltResult)r).ex) != null) { |
1324 |
> |
try { |
1325 |
> |
dst.complete(fn.apply(ex)); |
1326 |
> |
} catch (Throwable rex) { |
1327 |
> |
dst.completeExceptionally(rex); |
1328 |
> |
} |
1329 |
> |
return; |
1330 |
|
} |
1331 |
+ |
t = null; |
1332 |
|
} |
1333 |
+ |
else |
1334 |
+ |
t = (T) r; |
1335 |
+ |
dst.complete(t); |
1336 |
|
} |
1337 |
|
} |
1338 |
|
} |