if (isData == haveData) // can't match break; if (p.casItem(item, e)) { // match for (Node q = p; q != h;) { h.forgetNext(); break; (q = h.next) == null || !q.isMatched()) break; // unless slack < 2 s = new Node(e, haveData); Node pred = tryAppend(s, haveData); if (pred == null)
if (item != e) { // matched s.forgetContents(); // avoid garbage return LinkedTransferQueue.<E>cast(item); s.casItem(e, s)) { // cancel unsplice(pred, s); return e;
/** * Main implementation of remove(Object) */ private boolean findAndRemove(Object e) { if (e != null) { for (Node pred = null, p = head; p != null; ) { Object item = p.item; if (p.isData) { if (item != null && item != p && e.equals(item) && p.tryMatchData()) { unsplice(pred, p); return true; } } else if (item == null) break; pred = p; if ((p = p.next) == pred) { // stale pred = null; p = head; } } } return false; }
if (item != e) { // matched s.forgetContents(); // avoid garbage return this.<E>cast(item); s.casItem(e, s)) { // cancel unsplice(pred, s); return e;
if (isData == haveData) // can't match break; if (p.casItem(item, e)) { // match for (Node q = p; q != h;) { h.forgetNext(); break; (q = h.next) == null || !q.isMatched()) break; // unless slack < 2 s = new Node(e, haveData); Node pred = tryAppend(s, haveData); if (pred == null)
s.forgetContents(); // forget unneeded fields Node n = s.next; if (n == null || (n != s && pred.casNext(s, n) && pred.isMatched())) { for (;;) { // check if at, or could be, head Node h = head; if (h == pred || h == s || h == null) return; // at head or list empty if (!h.isMatched()) break; Node hn = h.next; return; // now empty if (hn != h && casHead(h, hn)) h.forgetNext(); // advance head
return s; // initialize else if (p.cannotPrecede(haveData)) return null; // lost race vs opposite mode else if ((n = p.next) != null) // not last; keep traversing else if (!p.casNext(null, s))
/** * Traverses and counts unmatched nodes of the given mode. * Used by methods size and getWaitingConsumerCount. */ private int countOfMode(boolean data) { int count = 0; for (Node p = head; p != null; ) { if (!p.isMatched()) { if (p.isData != data) return 0; if (++count == Integer.MAX_VALUE) // saturated break; } Node n = p.next; if (n != p) p = n; else { count = 0; p = head; } } return count; }
/** * Main implementation of remove(Object) */ private boolean findAndRemove(Object e) { if (e != null) { for (Node pred = null, p = head; p != null; ) { Object item = p.item; if (p.isData) { if (item != null && item != p && e.equals(item) && p.tryMatchData()) { unsplice(pred, p); return true; } } else if (item == null) break; pred = p; if ((p = p.next) == pred) { // stale pred = null; p = head; } } } return false; }
/** * Unlinks matched (typically cancelled) nodes encountered in a * traversal from head. */ private void sweep() { for (Node p = head, s, n; p != null && (s = p.next) != null; ) { if (!s.isMatched()) // Unmatched nodes are never self-linked p = s; else if ((n = s.next) == null) // trailing node is pinned break; else if (s == n) // stale // No need to also check for p == s, since that implies s == n p = head; else p.casNext(s, n); } }
/** * Returns spin/yield value for a node with given predecessor and * data mode. See above for explanation. */ private static int spinsFor(Node pred, boolean haveData) { if (MP && pred != null) { if (pred.isData != haveData) // phase change return FRONT_SPINS + CHAINED_SPINS; if (pred.isMatched()) // probably at front return FRONT_SPINS; if (pred.waiter == null) // pred apparently spinning return CHAINED_SPINS; } return 0; }
/** * Returns the first unmatched node of the given mode, or null if * none. Used by methods isEmpty, hasWaitingConsumer. */ private Node firstOfMode(boolean isData) { for (Node p = head; p != null; p = succ(p)) { if (!p.isMatched()) return (p.isData == isData) ? p : null; } return null; }
/** * Returns {@code true} if this queue contains no elements. * * @return {@code true} if this queue contains no elements */ public boolean isEmpty() { for (Node p = head; p != null; p = succ(p)) { if (!p.isMatched()) return !p.isData; } return true; }
/** * Tries to artificially match a data node -- used by remove. */ final boolean tryMatchData() { // assert isData; Object x = item; if (x != null && x != this && casItem(x, null)) { LockSupport.unpark(waiter); return true; } return false; }
s.forgetContents(); // forget unneeded fields Node n = s.next; if (n == null || (n != s && pred.casNext(s, n) && pred.isMatched())) { for (;;) { // check if at, or could be, head Node h = head; if (h == pred || h == s || h == null) return; // at head or list empty if (!h.isMatched()) break; Node hn = h.next; return; // now empty if (hn != h && casHead(h, hn)) h.forgetNext(); // advance head
return s; // initialize else if (p.cannotPrecede(haveData)) return null; // lost race vs opposite mode else if ((n = p.next) != null) // not last; keep traversing else if (!p.casNext(null, s))
/** * Traverses and counts unmatched nodes of the given mode. * Used by methods size and getWaitingConsumerCount. */ private int countOfMode(boolean data) { int count = 0; for (Node p = head; p != null; ) { if (!p.isMatched()) { if (p.isData != data) return 0; if (++count == Integer.MAX_VALUE) // saturated break; } Node n = p.next; if (n != p) p = n; else { count = 0; p = head; } } return count; }
/** * Unlinks matched (typically cancelled) nodes encountered in a * traversal from head. */ private void sweep() { for (Node p = head, s, n; p != null && (s = p.next) != null; ) { if (!s.isMatched()) // Unmatched nodes are never self-linked p = s; else if ((n = s.next) == null) // trailing node is pinned break; else if (s == n) // stale // No need to also check for p == s, since that implies s == n p = head; else p.casNext(s, n); } }
/** * Returns spin/yield value for a node with given predecessor and * data mode. See above for explanation. */ private static int spinsFor(Node pred, boolean haveData) { if (MP && pred != null) { if (pred.isData != haveData) // phase change return FRONT_SPINS + CHAINED_SPINS; if (pred.isMatched()) // probably at front return FRONT_SPINS; if (pred.waiter == null) // pred apparently spinning return CHAINED_SPINS; } return 0; }
/** * Returns {@code true} if this queue contains no elements. * * @return {@code true} if this queue contains no elements */ public boolean isEmpty() { for (Node p = head; p != null; p = succ(p)) { if (!p.isMatched()) return !p.isData; } return true; }