557 |
|
* Guarantees that any node which was unlinked before a call to |
558 |
|
* this method will be unreachable from head after it returns. |
559 |
|
* Does not guarantee to eliminate slack, only that head will |
560 |
< |
* point to a node that was active when this method was invoked. |
560 |
> |
* point to a node that was active while this method was running. |
561 |
|
*/ |
562 |
|
private final void updateHead() { |
563 |
< |
// We need to ensure head either already points to an active |
564 |
< |
// node, or that we or another thread updates it using casHead. |
565 |
< |
Node<E> h = head, p; |
566 |
< |
if (h.item == null && (p = h.prev) != null) |
567 |
< |
fullUpdateHead(h, p); |
568 |
< |
} |
569 |
< |
|
570 |
< |
private final void fullUpdateHead(Node<E> h, Node<E> p) { |
571 |
< |
for (Node<E> q;;) { |
572 |
< |
if ((q = p.prev) == null || |
573 |
< |
(q = (p = q).prev) == null) { |
574 |
< |
// It is possible that p is PREV_TERMINATOR, |
575 |
< |
// but if so, the CAS is guaranteed to fail. |
576 |
< |
casHead(h, p); |
577 |
< |
// If the CAS failed, someone else did our job for us. |
578 |
< |
return; |
563 |
> |
// Either head already points to an active node, or we keep |
564 |
> |
// trying to cas it to the first node until it does. |
565 |
> |
Node<E> h, p, q; |
566 |
> |
restartFromHead: |
567 |
> |
while ((h = head).item == null && (p = h.prev) != null) { |
568 |
> |
for (;;) { |
569 |
> |
if ((q = p.prev) == null || |
570 |
> |
(q = (p = q).prev) == null) { |
571 |
> |
// It is possible that p is PREV_TERMINATOR, |
572 |
> |
// but if so, the CAS is guaranteed to fail. |
573 |
> |
if (casHead(h, p)) |
574 |
> |
return; |
575 |
> |
else |
576 |
> |
continue restartFromHead; |
577 |
> |
} |
578 |
> |
else if (h != head) |
579 |
> |
continue restartFromHead; |
580 |
> |
else |
581 |
> |
p = q; |
582 |
|
} |
580 |
– |
else if (h != head) |
581 |
– |
return; |
582 |
– |
else |
583 |
– |
p = q; |
583 |
|
} |
584 |
|
} |
585 |
|
|
587 |
|
* Guarantees that any node which was unlinked before a call to |
588 |
|
* this method will be unreachable from tail after it returns. |
589 |
|
* Does not guarantee to eliminate slack, only that tail will |
590 |
< |
* point to a node that was active when this method was invoked. |
590 |
> |
* point to a node that was active while this method was running. |
591 |
|
*/ |
592 |
|
private final void updateTail() { |
593 |
< |
// We need to ensure tail either already points to an active |
594 |
< |
// node, or that we or another thread updates it using casTail. |
595 |
< |
Node<E> t = tail, p; |
596 |
< |
if (t.item == null && (p = t.next) != null) |
597 |
< |
fullUpdateTail(t, p); |
598 |
< |
} |
599 |
< |
|
600 |
< |
private final void fullUpdateTail(Node<E> t, Node<E> p) { |
601 |
< |
for (Node<E> q;;) { |
602 |
< |
if ((q = p.next) == null || |
603 |
< |
(q = (p = q).next) == null) { |
604 |
< |
// It is possible that p is PREV_TERMINATOR, |
605 |
< |
// but if so, the CAS is guaranteed to fail. |
606 |
< |
casTail(t, p); |
607 |
< |
// If the CAS failed, someone else did our job for us. |
608 |
< |
return; |
593 |
> |
// Either tail already points to an active node, or we keep |
594 |
> |
// trying to cas it to the last node until it does. |
595 |
> |
Node<E> t, p, q; |
596 |
> |
restartFromTail: |
597 |
> |
while ((t = tail).item == null && (p = t.next) != null) { |
598 |
> |
for (;;) { |
599 |
> |
if ((q = p.next) == null || |
600 |
> |
(q = (p = q).next) == null) { |
601 |
> |
// It is possible that p is NEXT_TERMINATOR, |
602 |
> |
// but if so, the CAS is guaranteed to fail. |
603 |
> |
if (casTail(t, p)) |
604 |
> |
return; |
605 |
> |
else |
606 |
> |
continue restartFromTail; |
607 |
> |
} |
608 |
> |
else if (t != tail) |
609 |
> |
continue restartFromTail; |
610 |
> |
else |
611 |
> |
p = q; |
612 |
|
} |
611 |
– |
else if (t != tail) |
612 |
– |
return; |
613 |
– |
else |
614 |
– |
p = q; |
613 |
|
} |
614 |
|
} |
615 |
|
|