All Downloads are FREE. Search and download functionalities are using the official Maven repository.

java.util.concurrent.ConcurrentLinkedQueue Maven / Gradle / Ivy

Go to download

JVM AOT compiler currently generating JavaScript, C++, Haxe, with initial focus on Kotlin and games.

There is a newer version: 0.6.8
Show newest version
/*
 * 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 java.util.*;

public class ConcurrentLinkedQueue extends AbstractQueue implements Queue, java.io.Serializable {
	private static class Node {
		volatile E item;
		volatile Node next;

		Node(E item) {
			set(item);
		}

		void set(E item) {
			this.item = item;
		}

		synchronized boolean casItem(E cmp, E val) {
			if (this.item == cmp) {
				this.item = val;
				return true;
			} else {
				return false;
			}
		}

		synchronized void lazySetNext(Node val) {
			this.next = val;
		}

		boolean casNext(Node cmp, Node val) {
			if (this.next == cmp) {
				this.next = val;
				return true;
			} else {
				return false;
			}
		}
	}

	private transient volatile Node head;
	private transient volatile Node tail;

	public ConcurrentLinkedQueue() {
		head = tail = new Node(null);
	}

	public ConcurrentLinkedQueue(Collection 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);
				t = newNode;
			}
		}
		if (h == null)
			h = t = new Node(null);
		head = h;
		tail = t;
	}

	public boolean add(E e) {
		return offer(e);
	}

	final void updateHead(Node h, Node p) {
		if (h != p && casHead(h, p)) h.lazySetNext(h);
	}

	final Node succ(Node p) {
		Node next = p.next;
		return (p == next) ? head : next;
	}

	public boolean offer(E e) {
		checkNotNull(e);
		final Node newNode = new Node(e);

		for (Node t = tail, p = t; ; ) {
			Node q = p.next;
			if (q == null) {
				if (p.casNext(null, newNode)) {
					if (p != t) casTail(t, newNode);
					return true;
				}
			} else if (p == q) {
				p = (t != (t = tail)) ? t : head;
			} else {
				p = (p != t && t != (t = tail)) ? t : q;
			}
		}
	}

	public E poll() {
		restartFromHead:
		for (; ; ) {
			for (Node h = head, p = h, q; ; ) {
				E item = p.item;

				if (item != null && p.casItem(item, null)) {
					if (p != h) updateHead(h, ((q = p.next) != null) ? q : p);
					return item;
				} else if ((q = p.next) == null) {
					updateHead(h, p);
					return null;
				} else if (p == q) {
					continue restartFromHead;
				} else {
					p = q;
				}
			}
		}
	}

	public E peek() {
		restartFromHead:
		for (; ; ) {
			for (Node h = head, p = h, q; ; ) {
				E item = p.item;
				if (item != null || (q = p.next) == null) {
					updateHead(h, p);
					return item;
				} else if (p == q)
					continue restartFromHead;
				else
					p = q;
			}
		}
	}

	Node first() {
		restartFromHead:
		for (; ; ) {
			for (Node h = head, p = h, q; ; ) {
				boolean hasItem = (p.item != null);
				if (hasItem || (q = p.next) == null) {
					updateHead(h, p);
					return hasItem ? p : null;
				} else if (p == q)
					continue restartFromHead;
				else
					p = q;
			}
		}
	}

	public boolean isEmpty() {
		return first() == null;
	}

	public int size() {
		int count = 0;
		for (Node p = first(); p != null; p = succ(p))
			if (p.item != null)
				// Collection.size() spec says to max out
				if (++count == Integer.MAX_VALUE)
					break;
		return count;
	}

	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 remove(Object o) {
		if (o == null) return false;
		Node pred = null;
		for (Node p = first(); p != null; p = succ(p)) {
			E item = p.item;
			if (item != null &&
				o.equals(item) &&
				p.casItem(item, null)) {
				Node next = succ(p);
				if (pred != null && next != null)
					pred.casNext(p, next);
				return true;
			}
			pred = p;
		}
		return false;
	}

	public boolean addAll(Collection 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);
				last = newNode;
			}
		}
		if (beginningOfTheEnd == null) return false;

		for (Node t = tail, p = t; ; ) {
			Node q = p.next;
			if (q == null) {
				if (p.casNext(null, beginningOfTheEnd)) {
					if (!casTail(t, last)) {
						t = tail;
						if (last.next == null) casTail(t, last);
					}
					return true;
				}
			} else if (p == q) {
				p = (t != (t = tail)) ? t : head;
			} else {
				p = (p != t && t != (t = tail)) ? t : q;
			}
		}
	}

	public Object[] toArray() {
		// Use ArrayList to deal with resizing.
		ArrayList al = new ArrayList();
		for (Node p = first(); p != null; p = succ(p)) {
			E item = p.item;
			if (item != null) al.add(item);
		}
		return al.toArray();
	}

	@SuppressWarnings("unchecked")
	public  T[] toArray(T[] a) {
		// try to use sent-in array
		int k = 0;
		Node p;
		for (p = first(); p != null && k < a.length; p = succ(p)) {
			E item = p.item;
			if (item != null)
				a[k++] = (T) item;
		}
		if (p == null) {
			if (k < a.length)
				a[k] = null;
			return a;
		}

		// If won't fit, use ArrayList version
		ArrayList al = new ArrayList();
		for (Node q = first(); q != null; q = succ(q)) {
			E item = q.item;
			if (item != null)
				al.add(item);
		}
		return al.toArray(a);
	}

	public Iterator iterator() {
		return new Itr();
	}

	private class Itr implements Iterator {
		private Node nextNode;
		private E nextItem;
		private Node lastRet;

		Itr() {
			advance();
		}

		private E advance() {
			lastRet = nextNode;
			E x = nextItem;

			Node pred, p;
			if (nextNode == null) {
				p = first();
				pred = null;
			} else {
				pred = nextNode;
				p = succ(nextNode);
			}

			for (; ; ) {
				if (p == null) {
					nextNode = null;
					nextItem = null;
					return x;
				}
				E item = p.item;
				if (item != null) {
					nextNode = p;
					nextItem = item;
					return x;
				} else {
					// skip over nulls
					Node next = succ(p);
					if (pred != null && next != null)
						pred.casNext(p, next);
					p = next;
				}
			}
		}

		public boolean hasNext() {
			return nextNode != null;
		}

		public E next() {
			if (nextNode == null) throw new NoSuchElementException();
			return advance();
		}

		public void remove() {
			Node l = lastRet;
			if (l == null) throw new IllegalStateException();
			// rely on a future traversal to relink.
			l.item = null;
			lastRet = null;
		}
	}

	private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException {
		s.defaultWriteObject();
		for (Node p = first(); p != null; p = succ(p)) {
			Object 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);
				t = newNode;
			}
		}
		if (h == null) h = t = new Node(null);
		head = h;
		tail = t;
	}

	private static void checkNotNull(Object v) {
		if (v == null) throw new NullPointerException();
	}

	synchronized private boolean casTail(Node cmp, Node val) {
		if (this.tail == cmp) {
			this.tail = val;
			return true;
		} else {
			return false;
		}
	}

	synchronized private boolean casHead(Node cmp, Node val) {
		if (this.head == cmp) {
			this.head = val;
			return true;
		} else {
			return false;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy