943 |
|
@SuppressWarnings("serial") |
944 |
|
static final class UniExceptionally<T> extends UniCompletion<T,T> { |
945 |
|
Function<? super Throwable, ? extends T> fn; |
946 |
< |
UniExceptionally(CompletableFuture<T> dep, CompletableFuture<T> src, |
946 |
> |
UniExceptionally(Executor executor, |
947 |
> |
CompletableFuture<T> dep, CompletableFuture<T> src, |
948 |
|
Function<? super Throwable, ? extends T> fn) { |
949 |
< |
super(null, dep, src); this.fn = fn; |
949 |
> |
super(executor, dep, src); this.fn = fn; |
950 |
|
} |
951 |
< |
final CompletableFuture<T> tryFire(int mode) { // never ASYNC |
951 |
< |
// assert mode != ASYNC; |
951 |
> |
final CompletableFuture<T> tryFire(int mode) { |
952 |
|
CompletableFuture<T> d; CompletableFuture<T> a; |
953 |
|
Object r; Function<? super Throwable, ? extends T> f; |
954 |
|
if ((d = dep) == null || (f = fn) == null |
955 |
|
|| (a = src) == null || (r = a.result) == null |
956 |
< |
|| !d.uniExceptionally(r, f, this)) |
956 |
> |
|| !d.uniExceptionally(r, f, mode > 0 ? null : this)) |
957 |
|
return null; |
958 |
|
dep = null; src = null; fn = null; |
959 |
|
return d.postFire(a, mode); |
966 |
|
Throwable x; |
967 |
|
if (result == null) { |
968 |
|
try { |
969 |
< |
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) { |
970 |
< |
if (c != null && !c.claim()) |
971 |
< |
return false; |
969 |
> |
if (c != null && !c.claim()) |
970 |
> |
return false; |
971 |
> |
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) |
972 |
|
completeValue(f.apply(x)); |
973 |
< |
} else |
973 |
> |
else |
974 |
|
internalComplete(r); |
975 |
|
} catch (Throwable ex) { |
976 |
|
completeThrowable(ex); |
980 |
|
} |
981 |
|
|
982 |
|
private CompletableFuture<T> uniExceptionallyStage( |
983 |
< |
Function<Throwable, ? extends T> f) { |
983 |
> |
Executor e, Function<Throwable, ? extends T> f) { |
984 |
|
if (f == null) throw new NullPointerException(); |
985 |
|
CompletableFuture<T> d = newIncompleteFuture(); |
986 |
|
Object r; |
987 |
|
if ((r = result) == null) |
988 |
< |
unipush(new UniExceptionally<T>(d, this, f)); |
989 |
< |
else |
988 |
> |
unipush(new UniExceptionally<T>(e, d, this, f)); |
989 |
> |
else if (e == null) |
990 |
|
d.uniExceptionally(r, f, null); |
991 |
+ |
else { |
992 |
+ |
try { |
993 |
+ |
e.execute(new UniExceptionally<T>(null, d, this, f)); |
994 |
+ |
} catch (Throwable ex) { |
995 |
+ |
d.result = encodeThrowable(ex); |
996 |
+ |
} |
997 |
+ |
} |
998 |
+ |
return d; |
999 |
+ |
} |
1000 |
+ |
|
1001 |
+ |
@SuppressWarnings("serial") |
1002 |
+ |
static final class UniComposeExceptionally<T> extends UniCompletion<T,T> { |
1003 |
+ |
Function<Throwable, ? extends CompletionStage<T>> fn; |
1004 |
+ |
UniComposeExceptionally(Executor executor, CompletableFuture<T> dep, |
1005 |
+ |
CompletableFuture<T> src, |
1006 |
+ |
Function<Throwable, ? extends CompletionStage<T>> fn) { |
1007 |
+ |
super(executor, dep, src); this.fn = fn; |
1008 |
+ |
} |
1009 |
+ |
final CompletableFuture<T> tryFire(int mode) { |
1010 |
+ |
CompletableFuture<T> d; CompletableFuture<T> a; |
1011 |
+ |
Function<Throwable, ? extends CompletionStage<T>> f; |
1012 |
+ |
Object r; Throwable x; |
1013 |
+ |
if ((d = dep) == null || (f = fn) == null |
1014 |
+ |
|| (a = src) == null || (r = a.result) == null) |
1015 |
+ |
return null; |
1016 |
+ |
if (d.result == null) { |
1017 |
+ |
if ((r instanceof AltResult) && |
1018 |
+ |
(x = ((AltResult)r).ex) != null) { |
1019 |
+ |
try { |
1020 |
+ |
if (mode <= 0 && !claim()) |
1021 |
+ |
return null; |
1022 |
+ |
CompletableFuture<T> g = f.apply(x).toCompletableFuture(); |
1023 |
+ |
if ((r = g.result) != null) |
1024 |
+ |
d.completeRelay(r); |
1025 |
+ |
else { |
1026 |
+ |
g.unipush(new UniRelay<T,T>(d, g)); |
1027 |
+ |
if (d.result == null) |
1028 |
+ |
return null; |
1029 |
+ |
} |
1030 |
+ |
} catch (Throwable ex) { |
1031 |
+ |
d.completeThrowable(ex); |
1032 |
+ |
} |
1033 |
+ |
} |
1034 |
+ |
else |
1035 |
+ |
d.internalComplete(r); |
1036 |
+ |
} |
1037 |
+ |
dep = null; src = null; fn = null; |
1038 |
+ |
return d.postFire(a, mode); |
1039 |
+ |
} |
1040 |
+ |
} |
1041 |
+ |
|
1042 |
+ |
private CompletableFuture<T> uniComposeExceptionallyStage( |
1043 |
+ |
Executor e, Function<Throwable, ? extends CompletionStage<T>> f) { |
1044 |
+ |
if (f == null) throw new NullPointerException(); |
1045 |
+ |
CompletableFuture<T> d = newIncompleteFuture(); |
1046 |
+ |
Object r, s; Throwable x; |
1047 |
+ |
if ((r = result) == null) |
1048 |
+ |
unipush(new UniComposeExceptionally<T>(e, d, this, f)); |
1049 |
+ |
else if (!(r instanceof AltResult) || (x = ((AltResult)r).ex) == null) |
1050 |
+ |
d.internalComplete(r); |
1051 |
+ |
else |
1052 |
+ |
try { |
1053 |
+ |
if (e != null) |
1054 |
+ |
e.execute(new UniComposeExceptionally<T>(null, d, this, f)); |
1055 |
+ |
else { |
1056 |
+ |
CompletableFuture<T> g = f.apply(x).toCompletableFuture(); |
1057 |
+ |
if ((s = g.result) != null) |
1058 |
+ |
d.result = encodeRelay(s); |
1059 |
+ |
else |
1060 |
+ |
g.unipush(new UniRelay<T,T>(d, g)); |
1061 |
+ |
} |
1062 |
+ |
} catch (Throwable ex) { |
1063 |
+ |
d.result = encodeThrowable(ex); |
1064 |
+ |
} |
1065 |
|
return d; |
1066 |
|
} |
1067 |
|
|
2345 |
|
return this; |
2346 |
|
} |
2347 |
|
|
2274 |
– |
// not in interface CompletionStage |
2275 |
– |
|
2276 |
– |
/** |
2277 |
– |
* Returns a new CompletableFuture that is completed when this |
2278 |
– |
* CompletableFuture completes, with the result of the given |
2279 |
– |
* function of the exception triggering this CompletableFuture's |
2280 |
– |
* completion when it completes exceptionally; otherwise, if this |
2281 |
– |
* CompletableFuture completes normally, then the returned |
2282 |
– |
* CompletableFuture also completes normally with the same value. |
2283 |
– |
* Note: More flexible versions of this functionality are |
2284 |
– |
* available using methods {@code whenComplete} and {@code handle}. |
2285 |
– |
* |
2286 |
– |
* @param fn the function to use to compute the value of the |
2287 |
– |
* returned CompletableFuture if this CompletableFuture completed |
2288 |
– |
* exceptionally |
2289 |
– |
* @return the new CompletableFuture |
2290 |
– |
*/ |
2348 |
|
public CompletableFuture<T> exceptionally( |
2349 |
|
Function<Throwable, ? extends T> fn) { |
2350 |
< |
return uniExceptionallyStage(fn); |
2350 |
> |
return uniExceptionallyStage(null, fn); |
2351 |
> |
} |
2352 |
> |
|
2353 |
> |
public CompletableFuture<T> exceptionallyAsync( |
2354 |
> |
Function<Throwable, ? extends T> fn) { |
2355 |
> |
return uniExceptionallyStage(defaultExecutor(), fn); |
2356 |
|
} |
2357 |
|
|
2358 |
+ |
public CompletableFuture<T> exceptionallyAsync( |
2359 |
+ |
Function<Throwable, ? extends T> fn, Executor executor) { |
2360 |
+ |
return uniExceptionallyStage(screenExecutor(executor), fn); |
2361 |
+ |
} |
2362 |
+ |
|
2363 |
+ |
public CompletableFuture<T> exceptionallyCompose( |
2364 |
+ |
Function<Throwable, ? extends CompletionStage<T>> fn) { |
2365 |
+ |
return uniComposeExceptionallyStage(null, fn); |
2366 |
+ |
} |
2367 |
+ |
|
2368 |
+ |
public CompletableFuture<T> exceptionallyComposeAsync( |
2369 |
+ |
Function<Throwable, ? extends CompletionStage<T>> fn) { |
2370 |
+ |
return uniComposeExceptionallyStage(defaultExecutor(), fn); |
2371 |
+ |
} |
2372 |
+ |
|
2373 |
+ |
public CompletableFuture<T> exceptionallyComposeAsync( |
2374 |
+ |
Function<Throwable, ? extends CompletionStage<T>> fn, |
2375 |
+ |
Executor executor) { |
2376 |
+ |
return uniComposeExceptionallyStage(screenExecutor(executor), fn); |
2377 |
+ |
} |
2378 |
|
|
2379 |
|
/* ------------- Arbitrary-arity constructions -------------- */ |
2380 |
|
|