196 |
|
return UNSAFE.compareAndSwapObject(this, STACK, cmp, val); |
197 |
|
} |
198 |
|
|
199 |
+ |
/** Returns true if successfully pushed c onto stack. */ |
200 |
+ |
final boolean tryPushStack(Completion c) { |
201 |
+ |
Completion h = stack; |
202 |
+ |
c.lazySetNext(h); |
203 |
+ |
return UNSAFE.compareAndSwapObject(this, STACK, h, c); |
204 |
+ |
} |
205 |
+ |
|
206 |
+ |
/** Unconditionally pushes c onto stack, retrying if necessary. */ |
207 |
+ |
final void pushStack(Completion c) { |
208 |
+ |
do {} while (!tryPushStack(c)); |
209 |
+ |
} |
210 |
+ |
|
211 |
|
/* ------------- Encoding and decoding outcomes -------------- */ |
212 |
|
|
213 |
|
static final class AltResult { // See above |
413 |
|
public final boolean exec() { tryFire(ASYNC); return true; } |
414 |
|
public final Void getRawResult() { return null; } |
415 |
|
public final void setRawResult(Void v) {} |
416 |
+ |
|
417 |
+ |
void lazySetNext(Completion val) { |
418 |
+ |
UNSAFE.putOrderedObject(this, NEXT, val); |
419 |
+ |
} |
420 |
+ |
|
421 |
+ |
// Unsafe mechanics |
422 |
+ |
|
423 |
+ |
private static final sun.misc.Unsafe UNSAFE; |
424 |
+ |
private static final long NEXT; |
425 |
+ |
|
426 |
+ |
static { |
427 |
+ |
try { |
428 |
+ |
UNSAFE = sun.misc.Unsafe.getUnsafe(); |
429 |
+ |
NEXT = UNSAFE.objectFieldOffset |
430 |
+ |
(Completion.class.getDeclaredField("next")); |
431 |
+ |
} catch (Exception e) { |
432 |
+ |
throw new Error(e); |
433 |
+ |
} |
434 |
+ |
} |
435 |
|
} |
436 |
|
|
437 |
|
/** |
450 |
|
CompletableFuture<?> d; Completion t; |
451 |
|
if (f.casStack(h, t = h.next)) { |
452 |
|
if (t != null) { |
453 |
< |
if (f != this) { // push |
454 |
< |
do {} while (!casStack(h.next = stack, h)); |
453 |
> |
if (f != this) { |
454 |
> |
pushStack(h); |
455 |
|
continue; |
456 |
|
} |
457 |
|
h.next = null; // detach |
522 |
|
/** Pushes the given completion (if it exists) unless done. */ |
523 |
|
final void push(UniCompletion<?,?> c) { |
524 |
|
if (c != null) { |
525 |
< |
while (result == null && !casStack(c.next = stack, c)) |
526 |
< |
c.next = null; // clear on failure |
525 |
> |
while (result == null && !tryPushStack(c)) |
526 |
> |
c.lazySetNext(null); // clear on failure |
527 |
|
} |
528 |
|
} |
529 |
|
|
1009 |
|
final void bipush(CompletableFuture<?> b, BiCompletion<?,?,?> c) { |
1010 |
|
if (c != null) { |
1011 |
|
Object r; |
1012 |
< |
while ((r = result) == null && !casStack(c.next = stack, c)) |
1013 |
< |
c.next = null; |
1012 |
> |
while ((r = result) == null && !tryPushStack(c)) |
1013 |
> |
c.lazySetNext(null); // clear on failure |
1014 |
|
if (b != null && b != this && b.result == null) { |
1015 |
|
Completion q = (r != null) ? c : new CoCompletion(c); |
1016 |
< |
while (b.result == null && !b.casStack(q.next = b.stack, q)) |
1017 |
< |
q.next = null; |
1016 |
> |
while (b.result == null && !b.tryPushStack(q)) |
1017 |
> |
q.lazySetNext(null); // clear on failure |
1018 |
|
} |
1019 |
|
} |
1020 |
|
} |
1296 |
|
final void orpush(CompletableFuture<?> b, BiCompletion<?,?,?> c) { |
1297 |
|
if (c != null) { |
1298 |
|
while ((b == null || b.result == null) && result == null) { |
1299 |
< |
if (casStack(c.next = stack, c)) { |
1299 |
> |
if (tryPushStack(c)) { |
1300 |
|
if (b != null && b != this && b.result == null) { |
1301 |
|
Completion q = new CoCompletion(c); |
1302 |
|
while (result == null && b.result == null && |
1303 |
< |
!b.casStack(q.next = b.stack, q)) |
1304 |
< |
q.next = null; |
1303 |
> |
!b.tryPushStack(q)) |
1304 |
> |
q.lazySetNext(null); // clear on failure |
1305 |
|
} |
1306 |
|
break; |
1307 |
|
} |
1308 |
< |
c.next = null; |
1308 |
> |
c.lazySetNext(null); // clear on failure |
1309 |
|
} |
1310 |
|
} |
1311 |
|
} |
1691 |
|
else if (q == null) |
1692 |
|
q = new Signaller(interruptible, 0L, 0L); |
1693 |
|
else if (!queued) |
1694 |
< |
queued = casStack(q.next = stack, q); |
1694 |
> |
queued = tryPushStack(q); |
1695 |
|
else if (interruptible && q.interruptControl < 0) { |
1696 |
|
q.thread = null; |
1697 |
|
cleanStack(); |
1733 |
|
Object r; |
1734 |
|
while ((r = result) == null) { |
1735 |
|
if (!queued) |
1736 |
< |
queued = casStack(q.next = stack, q); |
1736 |
> |
queued = tryPushStack(q); |
1737 |
|
else if (q.interruptControl < 0 || q.nanos <= 0L) { |
1738 |
|
q.thread = null; |
1739 |
|
cleanStack(); |