433 |
|
} |
434 |
|
|
435 |
|
final boolean casItem(Object cmp, Object val) { |
436 |
< |
// assert cmp == null || cmp.getClass() != Node.class; |
436 |
> |
// assert isData == (cmp != null); |
437 |
> |
// assert isData == (val == null); |
438 |
> |
// assert !(cmp instanceof Node); |
439 |
|
return ITEM.compareAndSet(this, cmp, val); |
440 |
|
} |
441 |
|
|
457 |
|
} |
458 |
|
|
459 |
|
/** |
460 |
< |
* Sets item to self and waiter to null, to avoid garbage |
461 |
< |
* retention after matching or cancelling. Uses relaxed writes |
462 |
< |
* because order is already constrained in the only calling |
463 |
< |
* contexts: item is forgotten only after volatile/atomic |
464 |
< |
* mechanics that extract items. Similarly, clearing waiter |
465 |
< |
* follows either CAS or return from park (if ever parked; |
466 |
< |
* else we don't care). |
460 |
> |
* Sets item (of a request node) to self and waiter to null, |
461 |
> |
* to avoid garbage retention after matching or cancelling. |
462 |
> |
* Uses relaxed writes because order is already constrained in |
463 |
> |
* the only calling contexts: item is forgotten only after |
464 |
> |
* volatile/atomic mechanics that extract items. Similarly, |
465 |
> |
* clearing waiter follows either CAS or return from park (if |
466 |
> |
* ever parked; else we don't care). |
467 |
|
*/ |
468 |
|
final void forgetContents() { |
469 |
< |
ITEM.set(this, this); |
469 |
> |
// assert isMatched(); |
470 |
> |
if (!isData) |
471 |
> |
ITEM.set(this, this); |
472 |
|
WAITER.set(this, null); |
473 |
|
} |
474 |
|
|
477 |
|
* case of artificial matches due to cancellation. |
478 |
|
*/ |
479 |
|
final boolean isMatched() { |
480 |
< |
Object x = item; |
477 |
< |
return (x == this) || ((x == null) == isData); |
480 |
> |
return isData == (item == null); |
481 |
|
} |
482 |
|
|
483 |
|
/** |
487 |
|
*/ |
488 |
|
final boolean cannotPrecede(boolean haveData) { |
489 |
|
boolean d = isData; |
490 |
< |
Object x; |
488 |
< |
return d != haveData && (x = item) != this && (x != null) == d; |
490 |
> |
return d != haveData && d != (item == null); |
491 |
|
} |
492 |
|
|
493 |
|
/** |
495 |
|
*/ |
496 |
|
final boolean tryMatchData() { |
497 |
|
// assert isData; |
498 |
< |
Object x = item; |
499 |
< |
if (x != null && x != this && casItem(x, null)) { |
498 |
> |
final Object x; |
499 |
> |
if ((x = item) != null && casItem(x, null)) { |
500 |
|
LockSupport.unpark(waiter); |
501 |
|
return true; |
502 |
|
} |
572 |
|
for (Node h = head, p = h; p != null;) { // find & match first node |
573 |
|
boolean isData = p.isData; |
574 |
|
Object item = p.item; |
575 |
< |
if (item != p && (item != null) == isData) { // unmatched |
575 |
> |
if ((item != null) == isData) { // unmatched |
576 |
|
if (isData == haveData) // can't match |
577 |
|
break; |
578 |
|
if (p.casItem(item, e)) { // match |
671 |
|
} |
672 |
|
else if (w.isInterrupted() || (timed && nanos <= 0L)) { |
673 |
|
// try to cancel and unlink |
674 |
< |
if (s.casItem(e, s)) { |
674 |
> |
if (s.casItem(e, s.isData ? null : s)) { |
675 |
|
unsplice(pred, s); |
676 |
|
return e; |
677 |
|
} |
730 |
|
|
731 |
|
/** |
732 |
|
* Returns the first unmatched data node, or null if none. |
733 |
< |
* Callers must recheck if the returned node's item field is null |
734 |
< |
* or self-linked before using. |
733 |
> |
* Callers must recheck if the returned node is unmatched |
734 |
> |
* before using. |
735 |
|
*/ |
736 |
|
final Node firstDataNode() { |
737 |
|
restartFromHead: for (;;) { |
738 |
|
for (Node p = head; p != null;) { |
739 |
|
Object item = p.item; |
740 |
|
if (p.isData) { |
741 |
< |
if (item != null && item != p) |
741 |
> |
if (item != null) |
742 |
|
return p; |
743 |
|
} |
744 |
|
else if (item == null) |
779 |
|
for (Node p = head; p != null;) { |
780 |
|
Object item = p.item; |
781 |
|
if (p.isData) { |
782 |
< |
if (item != null && item != p) { |
782 |
> |
if (item != null) { |
783 |
|
if (a == null) |
784 |
|
a = new String[4]; |
785 |
|
else if (size == a.length) |
808 |
|
for (Node p = head; p != null;) { |
809 |
|
Object item = p.item; |
810 |
|
if (p.isData) { |
811 |
< |
if (item != null && item != p) { |
811 |
> |
if (item != null) { |
812 |
|
if (x == null) |
813 |
|
x = new Object[4]; |
814 |
|
else if (size == x.length) |
936 |
|
} |
937 |
|
Object item = s.item; |
938 |
|
if (s.isData) { |
939 |
< |
if (item != null && item != s) { |
939 |
> |
if (item != null) { |
940 |
|
@SuppressWarnings("unchecked") E itemE = (E) item; |
941 |
|
nextItem = itemE; |
942 |
|
nextNode = s; |
1170 |
|
for (Node pred = null, p = head; p != null; ) { |
1171 |
|
Object item = p.item; |
1172 |
|
if (p.isData) { |
1173 |
< |
if (item != null && item != p && e.equals(item) && |
1173 |
> |
if (item != null && e.equals(item) && |
1174 |
|
p.tryMatchData()) { |
1175 |
|
unsplice(pred, p); |
1176 |
|
return true; |
1384 |
|
for (Node p = head; p != null;) { |
1385 |
|
Object item = p.item; |
1386 |
|
if (p.isData) { |
1387 |
< |
if (item != null && item != p) { |
1387 |
> |
if (item != null) { |
1388 |
|
@SuppressWarnings("unchecked") E e = (E) item; |
1389 |
|
return e; |
1390 |
|
} |
1412 |
|
for (Node p = head; p != null;) { |
1413 |
|
Object item = p.item; |
1414 |
|
if (p.isData) { |
1415 |
< |
if (item != null && item != p) |
1415 |
> |
if (item != null) |
1416 |
|
break; |
1417 |
|
} |
1418 |
|
else if (item == null) |
1472 |
|
for (Node p = head; p != null; p = succ(p)) { |
1473 |
|
Object item = p.item; |
1474 |
|
if (p.isData) { |
1475 |
< |
if (item != null && item != p && o.equals(item)) |
1475 |
> |
if (item != null && o.equals(item)) |
1476 |
|
return true; |
1477 |
|
} |
1478 |
|
else if (item == null) |