327 |
|
*/ |
328 |
|
static Object encodeRelay(Object r) { |
329 |
|
Throwable x; |
330 |
< |
return (((r instanceof AltResult) && |
331 |
< |
(x = ((AltResult)r).ex) != null && |
332 |
< |
!(x instanceof CompletionException)) ? |
333 |
< |
new AltResult(new CompletionException(x)) : r); |
330 |
> |
if (r instanceof AltResult |
331 |
> |
&& (x = ((AltResult)r).ex) != null |
332 |
> |
&& !(x instanceof CompletionException)) |
333 |
> |
r = new AltResult(new CompletionException(x)); |
334 |
> |
return r; |
335 |
|
} |
336 |
|
|
337 |
|
/** |
346 |
|
/** |
347 |
|
* Reports result using Future.get conventions. |
348 |
|
*/ |
349 |
< |
private static <T> T reportGet(Object r) |
349 |
> |
private static Object reportGet(Object r) |
350 |
|
throws InterruptedException, ExecutionException { |
351 |
|
if (r == null) // by convention below, null means interrupted |
352 |
|
throw new InterruptedException(); |
361 |
|
x = cause; |
362 |
|
throw new ExecutionException(x); |
363 |
|
} |
364 |
< |
@SuppressWarnings("unchecked") T t = (T) r; |
364 |
< |
return t; |
364 |
> |
return r; |
365 |
|
} |
366 |
|
|
367 |
|
/** |
368 |
|
* Decodes outcome to return result or throw unchecked exception. |
369 |
|
*/ |
370 |
< |
private static <T> T reportJoin(Object r) { |
370 |
> |
private static Object reportJoin(Object r) { |
371 |
|
if (r instanceof AltResult) { |
372 |
|
Throwable x; |
373 |
|
if ((x = ((AltResult)r).ex) == null) |
378 |
|
throw (CompletionException)x; |
379 |
|
throw new CompletionException(x); |
380 |
|
} |
381 |
< |
@SuppressWarnings("unchecked") T t = (T) r; |
382 |
< |
return t; |
381 |
> |
return r; |
382 |
|
} |
383 |
|
|
384 |
|
/* ------------- Async task preliminaries -------------- */ |
538 |
|
final boolean isLive() { return dep != null; } |
539 |
|
} |
540 |
|
|
541 |
< |
/** Pushes the given completion (if it exists) unless done. */ |
542 |
< |
final void push(UniCompletion<?,?> c) { |
541 |
> |
/** |
542 |
> |
* Pushes the given completion unless it completes while trying. |
543 |
> |
* Caller should have first checked that result is null. |
544 |
> |
*/ |
545 |
> |
final void unipush(UniCompletion<?,?> c) { |
546 |
|
if (c != null) { |
547 |
< |
while (result == null && !tryPushStack(c)) |
548 |
< |
lazySetNext(c, null); // clear on failure |
547 |
> |
while (!tryPushStack(c)) { |
548 |
> |
if (result != null) { |
549 |
> |
lazySetNext(c, null); |
550 |
> |
break; |
551 |
> |
} |
552 |
> |
} |
553 |
> |
if (result != null) |
554 |
> |
c.tryFire(SYNC); |
555 |
|
} |
556 |
|
} |
557 |
|
|
635 |
|
} |
636 |
|
} |
637 |
|
else { |
638 |
< |
push(c); |
631 |
< |
c.tryFire(SYNC); |
638 |
> |
unipush(c); |
639 |
|
} |
640 |
|
} |
641 |
|
return d; |
698 |
|
} |
699 |
|
} |
700 |
|
else { |
701 |
< |
push(c); |
695 |
< |
c.tryFire(SYNC); |
701 |
> |
unipush(c); |
702 |
|
} |
703 |
|
} |
704 |
|
return d; |
754 |
|
} |
755 |
|
} |
756 |
|
else { |
757 |
< |
push(c); |
752 |
< |
c.tryFire(SYNC); |
757 |
> |
unipush(c); |
758 |
|
} |
759 |
|
} |
760 |
|
return d; |
825 |
|
} |
826 |
|
} |
827 |
|
else { |
828 |
< |
push(c); |
824 |
< |
c.tryFire(SYNC); |
828 |
> |
unipush(c); |
829 |
|
} |
830 |
|
} |
831 |
|
return d; |
889 |
|
} |
890 |
|
} |
891 |
|
else { |
892 |
< |
push(c); |
889 |
< |
c.tryFire(SYNC); |
892 |
> |
unipush(c); |
893 |
|
} |
894 |
|
} |
895 |
|
return d; |
937 |
|
Function<Throwable, ? extends T> f) { |
938 |
|
if (f == null) throw new NullPointerException(); |
939 |
|
CompletableFuture<T> d = newIncompleteFuture(); |
940 |
< |
if (!d.uniExceptionally(this, f, null)) { |
941 |
< |
UniExceptionally<T> c = new UniExceptionally<T>(d, this, f); |
939 |
< |
push(c); |
940 |
< |
c.tryFire(SYNC); |
941 |
< |
} |
940 |
> |
if (!d.uniExceptionally(this, f, null)) |
941 |
> |
unipush(new UniExceptionally<T>(d, this, f)); |
942 |
|
return d; |
943 |
|
} |
944 |
|
|
971 |
|
if ((r = result) != null) |
972 |
|
d.completeRelay(r); |
973 |
|
else { |
974 |
< |
UniRelay<T> c = new UniRelay<T>(d, this); |
975 |
< |
push(c); |
976 |
< |
c.tryFire(SYNC); |
974 |
> |
unipush(new UniRelay<T>(d, this)); |
975 |
|
} |
976 |
|
return d; |
977 |
|
} |
981 |
|
if ((r = result) != null) |
982 |
|
return new MinimalStage<T>(encodeRelay(r)); |
983 |
|
MinimalStage<T> d = new MinimalStage<T>(); |
984 |
< |
UniRelay<T> c = new UniRelay<T>(d, this); |
987 |
< |
push(c); |
988 |
< |
c.tryFire(SYNC); |
984 |
> |
unipush(new UniRelay<T>(d, this)); |
985 |
|
return d; |
986 |
|
} |
987 |
|
|
1024 |
|
@SuppressWarnings("unchecked") S s = (S) r; |
1025 |
|
CompletableFuture<T> g = f.apply(s).toCompletableFuture(); |
1026 |
|
if (g.result == null || !uniRelay(g)) { |
1027 |
< |
UniRelay<T> copy = new UniRelay<T>(this, g); |
1032 |
< |
g.push(copy); |
1033 |
< |
copy.tryFire(SYNC); |
1027 |
> |
g.unipush(new UniRelay<T>(this, g)); |
1028 |
|
if (result == null) |
1029 |
|
return false; |
1030 |
|
} |
1054 |
|
if ((s = g.result) != null) |
1055 |
|
d.completeRelay(s); |
1056 |
|
else { |
1057 |
< |
UniRelay<V> c = new UniRelay<V>(d, g); |
1064 |
< |
g.push(c); |
1065 |
< |
c.tryFire(SYNC); |
1057 |
> |
g.unipush(new UniRelay<V>(d, g)); |
1058 |
|
} |
1059 |
|
return d; |
1060 |
|
} catch (Throwable ex) { |
1062 |
|
return d; |
1063 |
|
} |
1064 |
|
} |
1073 |
– |
UniCompose<T,V> c = new UniCompose<T,V>(e, d, this, f); |
1065 |
|
if (r != null && e != null) { |
1066 |
|
try { |
1067 |
|
e.execute(new UniCompose<T,V>(null, d, this, f)); |
1070 |
|
} |
1071 |
|
} |
1072 |
|
else { |
1073 |
< |
push(c); |
1083 |
< |
c.tryFire(SYNC); |
1073 |
> |
unipush(new UniCompose<T,V>(e, d, this, f)); |
1074 |
|
} |
1075 |
|
return d; |
1076 |
|
} |
2013 |
|
* @throws InterruptedException if the current thread was interrupted |
2014 |
|
* while waiting |
2015 |
|
*/ |
2016 |
+ |
@SuppressWarnings("unchecked") |
2017 |
|
public T get() throws InterruptedException, ExecutionException { |
2018 |
|
Object r; |
2019 |
< |
return reportGet((r = result) == null ? waitingGet(true) : r); |
2019 |
> |
if ((r = result) == null) |
2020 |
> |
r = waitingGet(true); |
2021 |
> |
return (T) reportGet(r); |
2022 |
|
} |
2023 |
|
|
2024 |
|
/** |
2034 |
|
* while waiting |
2035 |
|
* @throws TimeoutException if the wait timed out |
2036 |
|
*/ |
2037 |
+ |
@SuppressWarnings("unchecked") |
2038 |
|
public T get(long timeout, TimeUnit unit) |
2039 |
|
throws InterruptedException, ExecutionException, TimeoutException { |
2046 |
– |
Object r; |
2040 |
|
long nanos = unit.toNanos(timeout); |
2041 |
< |
return reportGet((r = result) == null ? timedGet(nanos) : r); |
2041 |
> |
Object r; |
2042 |
> |
if ((r = result) == null) |
2043 |
> |
r = timedGet(nanos); |
2044 |
> |
return (T) reportGet(r); |
2045 |
|
} |
2046 |
|
|
2047 |
|
/** |
2058 |
|
* @throws CompletionException if this future completed |
2059 |
|
* exceptionally or a completion computation threw an exception |
2060 |
|
*/ |
2061 |
+ |
@SuppressWarnings("unchecked") |
2062 |
|
public T join() { |
2063 |
|
Object r; |
2064 |
< |
return reportJoin((r = result) == null ? waitingGet(false) : r); |
2064 |
> |
if ((r = result) == null) |
2065 |
> |
r = waitingGet(false); |
2066 |
> |
return (T) reportJoin(r); |
2067 |
|
} |
2068 |
|
|
2069 |
|
/** |
2076 |
|
* @throws CompletionException if this future completed |
2077 |
|
* exceptionally or a completion computation threw an exception |
2078 |
|
*/ |
2079 |
+ |
@SuppressWarnings("unchecked") |
2080 |
|
public T getNow(T valueIfAbsent) { |
2081 |
|
Object r; |
2082 |
< |
return ((r = result) == null) ? valueIfAbsent : reportJoin(r); |
2082 |
> |
return ((r = result) == null) ? valueIfAbsent : (T) reportJoin(r); |
2083 |
|
} |
2084 |
|
|
2085 |
|
/** |