6 |
|
|
7 |
|
package java.util.concurrent; |
8 |
|
|
9 |
+ |
import java.lang.invoke.MethodHandles; |
10 |
+ |
import java.lang.invoke.VarHandle; |
11 |
|
import java.util.concurrent.locks.LockSupport; |
12 |
|
import java.util.function.BiConsumer; |
13 |
|
import java.util.function.BiFunction; |
225 |
|
volatile Completion stack; // Top of Treiber stack of dependent actions |
226 |
|
|
227 |
|
final boolean internalComplete(Object r) { // CAS from null to r |
228 |
< |
return U.compareAndSwapObject(this, RESULT, null, r); |
227 |
< |
} |
228 |
< |
|
229 |
< |
final boolean casStack(Completion cmp, Completion val) { |
230 |
< |
return U.compareAndSwapObject(this, STACK, cmp, val); |
228 |
> |
return RESULT.compareAndSet(this, (Object)null, r); |
229 |
|
} |
230 |
|
|
231 |
|
/** Returns true if successfully pushed c onto stack. */ |
232 |
|
final boolean tryPushStack(Completion c) { |
233 |
|
Completion h = stack; |
234 |
< |
lazySetNext(c, h); |
235 |
< |
return U.compareAndSwapObject(this, STACK, h, c); |
234 |
> |
NEXT.setRelease(c, h); |
235 |
> |
return STACK.compareAndSet(this, h, c); |
236 |
|
} |
237 |
|
|
238 |
|
/** Unconditionally pushes c onto stack, retrying if necessary. */ |
252 |
|
|
253 |
|
/** Completes with the null value, unless already completed. */ |
254 |
|
final boolean completeNull() { |
255 |
< |
return U.compareAndSwapObject(this, RESULT, null, |
258 |
< |
NIL); |
255 |
> |
return RESULT.compareAndSet(this, (Object)null, (Object)NIL); |
256 |
|
} |
257 |
|
|
258 |
|
/** Returns the encoding of the given non-exceptional value. */ |
262 |
|
|
263 |
|
/** Completes with a non-exceptional result, unless already completed. */ |
264 |
|
final boolean completeValue(T t) { |
265 |
< |
return U.compareAndSwapObject(this, RESULT, null, |
269 |
< |
(t == null) ? NIL : t); |
265 |
> |
return RESULT.compareAndSet(this, (Object)null, (t == null) ? NIL : t); |
266 |
|
} |
267 |
|
|
268 |
|
/** |
276 |
|
|
277 |
|
/** Completes with an exceptional result, unless already completed. */ |
278 |
|
final boolean completeThrowable(Throwable x) { |
279 |
< |
return U.compareAndSwapObject(this, RESULT, null, |
284 |
< |
encodeThrowable(x)); |
279 |
> |
return RESULT.compareAndSet(this, (Object)null, encodeThrowable(x)); |
280 |
|
} |
281 |
|
|
282 |
|
/** |
303 |
|
* existing CompletionException. |
304 |
|
*/ |
305 |
|
final boolean completeThrowable(Throwable x, Object r) { |
306 |
< |
return U.compareAndSwapObject(this, RESULT, null, |
312 |
< |
encodeThrowable(x, r)); |
306 |
> |
return RESULT.compareAndSet(this, (Object)null, encodeThrowable(x, r)); |
307 |
|
} |
308 |
|
|
309 |
|
/** |
333 |
|
* If exceptional, r is first coerced to a CompletionException. |
334 |
|
*/ |
335 |
|
final boolean completeRelay(Object r) { |
336 |
< |
return U.compareAndSwapObject(this, RESULT, null, |
343 |
< |
encodeRelay(r)); |
336 |
> |
return RESULT.compareAndSet(this, (Object)null, encodeRelay(r)); |
337 |
|
} |
338 |
|
|
339 |
|
/** |
441 |
|
public final void setRawResult(Void v) {} |
442 |
|
} |
443 |
|
|
451 |
– |
static void lazySetNext(Completion c, Completion next) { |
452 |
– |
U.putObjectRelease(c, NEXT, next); |
453 |
– |
} |
454 |
– |
|
455 |
– |
static boolean casNext(Completion c, Completion cmp, Completion val) { |
456 |
– |
return U.compareAndSwapObject(c, NEXT, cmp, val); |
457 |
– |
} |
458 |
– |
|
444 |
|
/** |
445 |
|
* Pops and tries to trigger all reachable dependents. Call only |
446 |
|
* when known to be done. |
455 |
|
while ((h = f.stack) != null || |
456 |
|
(f != this && (h = (f = this).stack) != null)) { |
457 |
|
CompletableFuture<?> d; Completion t; |
458 |
< |
if (f.casStack(h, t = h.next)) { |
458 |
> |
if (STACK.compareAndSet(f, h, t = h.next)) { |
459 |
|
if (t != null) { |
460 |
|
if (f != this) { |
461 |
|
pushStack(h); |
462 |
|
continue; |
463 |
|
} |
464 |
< |
casNext(h, t, null); // try to detach |
464 |
> |
NEXT.compareAndSet(h, t, (Completion)null); // try to detach |
465 |
|
} |
466 |
|
f = (d = h.tryFire(NESTED)) == null ? this : d; |
467 |
|
} |
473 |
|
boolean unlinked = false; |
474 |
|
Completion p; |
475 |
|
while ((p = stack) != null && !p.isLive()) // ensure head of stack live |
476 |
< |
unlinked = casStack(p, p.next); |
476 |
> |
unlinked = STACK.compareAndSet(this, p, p.next); |
477 |
|
if (p != null && !unlinked) { // try to unlink first nonlive |
478 |
|
for (Completion q = p.next; q != null;) { |
479 |
|
Completion s = q.next; |
482 |
|
q = s; |
483 |
|
} |
484 |
|
else { |
485 |
< |
casNext(p, q, s); |
485 |
> |
NEXT.compareAndSet(p, q, s); |
486 |
|
break; |
487 |
|
} |
488 |
|
} |
531 |
|
if (c != null) { |
532 |
|
while (!tryPushStack(c)) { |
533 |
|
if (result != null) { |
534 |
< |
lazySetNext(c, null); |
534 |
> |
NEXT.setRelease(c, (Completion)null); |
535 |
|
break; |
536 |
|
} |
537 |
|
} |
1095 |
|
if (c != null) { |
1096 |
|
Object r; |
1097 |
|
while ((r = result) == null && !tryPushStack(c)) |
1098 |
< |
lazySetNext(c, null); // clear on failure |
1098 |
> |
NEXT.setRelease(c, (Completion)null); // clear on failure |
1099 |
|
if (b != null && b != this && b.result == null) { |
1100 |
|
Completion q = (r != null) ? c : new CoCompletion(c); |
1101 |
|
while (b.result == null && !b.tryPushStack(q)) |
1102 |
< |
lazySetNext(q, null); // clear on failure |
1102 |
> |
NEXT.setRelease(q, (Completion)null); // clear on failure |
1103 |
|
} |
1104 |
|
} |
1105 |
|
} |
1414 |
|
Completion q = new CoCompletion(c); |
1415 |
|
while (result == null && b.result == null && |
1416 |
|
!b.tryPushStack(q)) |
1417 |
< |
lazySetNext(q, null); // clear on failure |
1417 |
> |
NEXT.setRelease(q, (Completion)null); // clear on failure |
1418 |
|
} |
1419 |
|
break; |
1420 |
|
} |
1421 |
< |
lazySetNext(c, null); // clear on failure |
1421 |
> |
NEXT.setRelease(c, (Completion)null); // clear on failure |
1422 |
|
} |
1423 |
|
} |
1424 |
|
} |
2841 |
|
throw new UnsupportedOperationException(); } |
2842 |
|
} |
2843 |
|
|
2844 |
< |
// Unsafe mechanics |
2845 |
< |
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); |
2846 |
< |
private static final long RESULT; |
2847 |
< |
private static final long STACK; |
2863 |
< |
private static final long NEXT; |
2844 |
> |
// VarHandle mechanics |
2845 |
> |
private static final VarHandle RESULT; |
2846 |
> |
private static final VarHandle STACK; |
2847 |
> |
private static final VarHandle NEXT; |
2848 |
|
static { |
2849 |
|
try { |
2850 |
< |
RESULT = U.objectFieldOffset |
2851 |
< |
(CompletableFuture.class.getDeclaredField("result")); |
2852 |
< |
STACK = U.objectFieldOffset |
2853 |
< |
(CompletableFuture.class.getDeclaredField("stack")); |
2870 |
< |
NEXT = U.objectFieldOffset |
2871 |
< |
(Completion.class.getDeclaredField("next")); |
2850 |
> |
MethodHandles.Lookup l = MethodHandles.lookup(); |
2851 |
> |
RESULT = l.findVarHandle(CompletableFuture.class, "result", Object.class); |
2852 |
> |
STACK = l.findVarHandle(CompletableFuture.class, "stack", Completion.class); |
2853 |
> |
NEXT = l.findVarHandle(Completion.class, "next", Completion.class); |
2854 |
|
} catch (ReflectiveOperationException e) { |
2855 |
|
throw new Error(e); |
2856 |
|
} |