Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
java.util.concurrent.ConcurrentLinkedDeque Maven / Gradle / Ivy
Go to download
JVM AOT compiler currently generating JavaScript, C++, Haxe, with initial focus on Kotlin and games.
/*
* Written by Doug Lea and Martin Buchholz with assistance from members of
* JCP JSR-166 Expert Group and released to the public domain, as explained
* at http://creativecommons.org/publicdomain/zero/1.0/
*/
package java.util.concurrent;
import libcore.ConcurrentTools;
import java.util.*;
public class ConcurrentLinkedDeque extends AbstractCollection implements Deque, java.io.Serializable {
private transient volatile Node head;
private transient volatile Node tail;
private static final Node PREV_TERMINATOR, NEXT_TERMINATOR;
@SuppressWarnings("unchecked")
Node prevTerminator() {
return (Node) PREV_TERMINATOR;
}
@SuppressWarnings("unchecked")
Node nextTerminator() {
return (Node) NEXT_TERMINATOR;
}
static final class Node {
volatile Node prev;
volatile E item;
volatile Node next;
Node() {
}
Node(E item) {
this.item = item;
}
boolean casItem(E cmp, E val) {
if (ConcurrentTools.cmp(this.item, cmp)) {
this.item = val;
return true;
} else {
return false;
}
}
void lazySetNext(Node val) {
this.next = val;
}
boolean casNext(Node cmp, Node val) {
if (ConcurrentTools.cmp(this.next, cmp)) {
this.next = val;
return true;
} else {
return false;
}
}
void lazySetPrev(Node val) {
this.prev = val;
}
boolean casPrev(Node cmp, Node val) {
if (ConcurrentTools.cmp(this.prev, cmp)) {
this.prev = val;
return true;
} else {
return false;
}
}
}
private void linkFirst(E e) {
checkNotNull(e);
final Node newNode = new Node(e);
restartFromHead:
for (; ; ) {
for (Node h = head, p = h, q; ; ) {
if ((q = p.prev) != null &&
(q = (p = q).prev) != null)
p = (h != (h = head)) ? h : q;
else if (p.next == p) {
continue restartFromHead;
} else {
newNode.lazySetNext(p);
if (p.casPrev(null, newNode)) {
if (p != h) casHead(h, newNode);
return;
}
}
}
}
}
private void linkLast(E e) {
checkNotNull(e);
final Node newNode = new Node(e);
restartFromTail:
for (; ; ) {
for (Node t = tail, p = t, q; ; ) {
if ((q = p.next) != null && (q = (p = q).next) != null) {
p = (t != (t = tail)) ? t : q;
} else if (p.prev == p) {
continue restartFromTail;
} else {
newNode.lazySetPrev(p);
if (p.casNext(null, newNode)) {
if (p != t) casTail(t, newNode);
return;
}
}
}
}
}
private static final int HOPS = 2;
void unlink(Node x) {
final Node prev = x.prev;
final Node next = x.next;
if (prev == null) {
unlinkFirst(x, next);
} else if (next == null) {
unlinkLast(x, prev);
} else {
Node activePred, activeSucc;
boolean isFirst, isLast;
int hops = 1;
// Find active predecessor
for (Node p = prev; ; ++hops) {
if (p.item != null) {
activePred = p;
isFirst = false;
break;
}
Node q = p.prev;
if (q == null) {
if (p.next == p)
return;
activePred = p;
isFirst = true;
break;
} else if (p == q) {
return;
} else {
p = q;
}
}
for (Node p = next; ; ++hops) {
if (p.item != null) {
activeSucc = p;
isLast = false;
break;
}
Node q = p.next;
if (q == null) {
if (p.prev == p) return;
activeSucc = p;
isLast = true;
break;
} else if (p == q) {
return;
} else {
p = q;
}
}
if (hops < HOPS && (isFirst | isLast)) return;
skipDeletedSuccessors(activePred);
skipDeletedPredecessors(activeSucc);
// Try to gc-unlink, if possible
if ((isFirst | isLast) &&
(activePred.next == activeSucc) &&
(activeSucc.prev == activePred) &&
(isFirst ? activePred.prev == null : activePred.item != null) &&
(isLast ? activeSucc.next == null : activeSucc.item != null)
) {
updateHead(); // Ensure x is not reachable from head
updateTail(); // Ensure x is not reachable from tail
// Finally, actually gc-unlink
x.lazySetPrev(isFirst ? prevTerminator() : x);
x.lazySetNext(isLast ? nextTerminator() : x);
}
}
}
private void unlinkFirst(Node first, Node next) {
for (Node o = null, p = next, q; ; ) {
if (p.item != null || (q = p.next) == null) {
if (o != null && p.prev != p && first.casNext(next, p)) {
skipDeletedPredecessors(p);
if (first.prev == null &&
(p.next == null || p.item != null) &&
p.prev == first) {
updateHead();
updateTail();
o.lazySetNext(o);
o.lazySetPrev(prevTerminator());
}
}
return;
} else if (p == q) {
return;
} else {
o = p;
p = q;
}
}
}
private void unlinkLast(Node last, Node prev) {
for (Node o = null, p = prev, q; ; ) {
if (p.item != null || (q = p.prev) == null) {
if (o != null && p.next != p && last.casPrev(prev, p)) {
skipDeletedSuccessors(p);
if (last.next == null &&
(p.prev == null || p.item != null) &&
p.next == last) {
updateHead();
updateTail();
o.lazySetPrev(o);
o.lazySetNext(nextTerminator());
}
}
return;
} else if (p == q) {
return;
} else {
o = p;
p = q;
}
}
}
private final void updateHead() {
Node h, p, q;
restartFromHead:
while ((h = head).item == null && (p = h.prev) != null) {
for (; ; ) {
if ((q = p.prev) == null ||
(q = (p = q).prev) == null) {
if (casHead(h, p)) {
return;
} else {
continue restartFromHead;
}
} else if (h != head) {
continue restartFromHead;
} else {
p = q;
}
}
}
}
private final void updateTail() {
Node t, p, q;
restartFromTail:
while ((t = tail).item == null && (p = t.next) != null) {
for (; ; ) {
if ((q = p.next) == null ||
(q = (p = q).next) == null) {
if (casTail(t, p)) return;
else continue restartFromTail;
} else if (t != tail) {
continue restartFromTail;
} else {
p = q;
}
}
}
}
private void skipDeletedPredecessors(Node x) {
whileActive:
do {
Node prev = x.prev;
Node p = prev;
findActive:
for (; ; ) {
if (p.item != null) break findActive;
Node q = p.prev;
if (q == null) {
if (p.next == p) continue whileActive;
break findActive;
} else if (p == q) {
continue whileActive;
} else {
p = q;
}
}
if (prev == p || x.casPrev(prev, p)) return;
} while (x.item != null || x.next == null);
}
private void skipDeletedSuccessors(Node x) {
whileActive:
do {
Node next = x.next;
Node p = next;
findActive:
for (; ; ) {
if (p.item != null) break findActive;
Node q = p.next;
if (q == null) {
if (p.prev == p) continue whileActive;
break findActive;
} else if (p == q) {
continue whileActive;
} else {
p = q;
}
}
if (next == p || x.casNext(next, p)) return;
} while (x.item != null || x.prev == null);
}
final Node succ(Node p) {
// TODO: should we skip deleted nodes here?
Node q = p.next;
return (p == q) ? first() : q;
}
final Node pred(Node p) {
Node q = p.prev;
return (p == q) ? last() : q;
}
Node first() {
restartFromHead:
for (; ; )
for (Node h = head, p = h, q; ; ) {
if ((q = p.prev) != null &&
(q = (p = q).prev) != null)
p = (h != (h = head)) ? h : q;
else if (p == h || casHead(h, p)) {
return p;
} else {
continue restartFromHead;
}
}
}
Node last() {
restartFromTail:
for (; ; )
for (Node t = tail, p = t, q; ; ) {
if ((q = p.next) != null &&
(q = (p = q).next) != null)
p = (t != (t = tail)) ? t : q;
else if (p == t || casTail(t, p)) {
return p;
} else {
continue restartFromTail;
}
}
}
private static void checkNotNull(Object v) {
if (v == null) throw new NullPointerException();
}
private E screenNullResult(E v) {
if (v == null) throw new NoSuchElementException();
return v;
}
private ArrayList toArrayList() {
ArrayList list = new ArrayList();
for (Node p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null) list.add(item);
}
return list;
}
public ConcurrentLinkedDeque() {
head = tail = new Node(null);
}
public ConcurrentLinkedDeque(Collection extends E> c) {
Node h = null, t = null;
for (E e : c) {
checkNotNull(e);
Node newNode = new Node(e);
if (h == null) {
h = t = newNode;
} else {
t.lazySetNext(newNode);
newNode.lazySetPrev(t);
t = newNode;
}
}
initHeadTail(h, t);
}
private void initHeadTail(Node h, Node t) {
if (h == t) {
if (h == null) {
h = t = new Node(null);
} else {
// Avoid edge case of a single Node with non-null item.
Node newNode = new Node(null);
t.lazySetNext(newNode);
newNode.lazySetPrev(t);
t = newNode;
}
}
head = h;
tail = t;
}
public void addFirst(E e) {
linkFirst(e);
}
public void addLast(E e) {
linkLast(e);
}
public boolean offerFirst(E e) {
linkFirst(e);
return true;
}
public boolean offerLast(E e) {
linkLast(e);
return true;
}
public E peekFirst() {
for (Node p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null) return item;
}
return null;
}
public E peekLast() {
for (Node p = last(); p != null; p = pred(p)) {
E item = p.item;
if (item != null) return item;
}
return null;
}
public E getFirst() {
return screenNullResult(peekFirst());
}
public E getLast() {
return screenNullResult(peekLast());
}
public E pollFirst() {
for (Node p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null && p.casItem(item, null)) {
unlink(p);
return item;
}
}
return null;
}
public E pollLast() {
for (Node p = last(); p != null; p = pred(p)) {
E item = p.item;
if (item != null && p.casItem(item, null)) {
unlink(p);
return item;
}
}
return null;
}
public E removeFirst() {
return screenNullResult(pollFirst());
}
public E removeLast() {
return screenNullResult(pollLast());
}
public boolean offer(E e) {
return offerLast(e);
}
public boolean add(E e) {
return offerLast(e);
}
public E poll() {
return pollFirst();
}
public E remove() {
return removeFirst();
}
public E peek() {
return peekFirst();
}
public E element() {
return getFirst();
}
public void push(E e) {
addFirst(e);
}
public E pop() {
return removeFirst();
}
public boolean removeFirstOccurrence(Object o) {
checkNotNull(o);
for (Node p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null && o.equals(item) && p.casItem(item, null)) {
unlink(p);
return true;
}
}
return false;
}
public boolean removeLastOccurrence(Object o) {
checkNotNull(o);
for (Node p = last(); p != null; p = pred(p)) {
E item = p.item;
if (item != null && o.equals(item) && p.casItem(item, null)) {
unlink(p);
return true;
}
}
return false;
}
public boolean contains(Object o) {
if (o == null) return false;
for (Node p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null && o.equals(item)) return true;
}
return false;
}
public boolean isEmpty() {
return peekFirst() == null;
}
public int size() {
int count = 0;
for (Node p = first(); p != null; p = succ(p)) if (p.item != null) if (++count == Integer.MAX_VALUE) break;
return count;
}
public boolean remove(Object o) {
return removeFirstOccurrence(o);
}
public boolean addAll(Collection extends E> c) {
if (c == this) throw new IllegalArgumentException();
Node beginningOfTheEnd = null, last = null;
for (E e : c) {
checkNotNull(e);
Node newNode = new Node(e);
if (beginningOfTheEnd == null) {
beginningOfTheEnd = last = newNode;
} else {
last.lazySetNext(newNode);
newNode.lazySetPrev(last);
last = newNode;
}
}
if (beginningOfTheEnd == null) return false;
restartFromTail:
for (; ; )
for (Node t = tail, p = t, q; ; ) {
if ((q = p.next) != null && (q = (p = q).next) != null) {
p = (t != (t = tail)) ? t : q;
} else if (p.prev == p) {
continue restartFromTail;
} else {
beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
if (p.casNext(null, beginningOfTheEnd)) {
if (!casTail(t, last)) {
t = tail;
if (last.next == null) casTail(t, last);
}
return true;
}
}
}
}
public void clear() {
while (pollFirst() != null)
;
}
public Object[] toArray() {
return toArrayList().toArray();
}
public T[] toArray(T[] a) {
return toArrayList().toArray(a);
}
public Iterator iterator() {
return new Itr();
}
public Iterator descendingIterator() {
return new DescendingItr();
}
private abstract class AbstractItr implements Iterator {
private Node nextNode;
private E nextItem;
private Node lastRet;
abstract Node startNode();
abstract Node nextNode(Node p);
AbstractItr() {
advance();
}
private void advance() {
lastRet = nextNode;
Node p = (nextNode == null) ? startNode() : nextNode(nextNode);
for (; ; p = nextNode(p)) {
if (p == null) {
nextNode = null;
nextItem = null;
break;
}
E item = p.item;
if (item != null) {
nextNode = p;
nextItem = item;
break;
}
}
}
public boolean hasNext() {
return nextItem != null;
}
public E next() {
E item = nextItem;
if (item == null) throw new NoSuchElementException();
advance();
return item;
}
public void remove() {
Node l = lastRet;
if (l == null) throw new IllegalStateException();
l.item = null;
unlink(l);
lastRet = null;
}
}
private class Itr extends AbstractItr {
Node startNode() {
return first();
}
Node nextNode(Node p) {
return succ(p);
}
}
private class DescendingItr extends AbstractItr {
Node startNode() {
return last();
}
Node nextNode(Node p) {
return pred(p);
}
}
private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
s.defaultWriteObject();
for (Node p = first(); p != null; p = succ(p)) {
E item = p.item;
if (item != null) s.writeObject(item);
}
s.writeObject(null);
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
Node h = null, t = null;
Object item;
while ((item = s.readObject()) != null) {
@SuppressWarnings("unchecked")
Node newNode = new Node((E) item);
if (h == null)
h = t = newNode;
else {
t.lazySetNext(newNode);
newNode.lazySetPrev(t);
t = newNode;
}
}
initHeadTail(h, t);
}
private boolean casHead(Node cmp, Node val) {
if (ConcurrentTools.cmp(this.head, cmp)) {
this.head = val;
return true;
} else {
return false;
}
}
private boolean casTail(Node cmp, Node val) {
if (ConcurrentTools.cmp(this.tail, cmp)) {
this.tail = val;
return true;
} else {
return false;
}
}
static {
PREV_TERMINATOR = new Node();
PREV_TERMINATOR.next = PREV_TERMINATOR;
NEXT_TERMINATOR = new Node();
NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
}
}