ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentLinkedQueue.java
Revision: 1.32
Committed: Mon May 16 08:54:27 2005 UTC (19 years, 1 month ago) by jsr166
Branch: MAIN
Changes since 1.31: +5 -9 lines
Log Message:
doc fixes

File Contents

# User Rev Content
1 dl 1.1 /*
2     * Written by Doug Lea with assistance from members of JCP JSR-166
3 dl 1.24 * Expert Group and released to the public domain, as explained at
4     * http://creativecommons.org/licenses/publicdomain
5 dl 1.1 */
6    
7     package java.util.concurrent;
8     import java.util.*;
9     import java.util.concurrent.atomic.*;
10    
11    
12     /**
13 jsr166 1.29 * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
14 dholmes 1.6 * This queue orders elements FIFO (first-in-first-out).
15     * The <em>head</em> of the queue is that element that has been on the
16     * queue the longest time.
17     * The <em>tail</em> of the queue is that element that has been on the
18 dl 1.17 * queue the shortest time. New elements
19     * are inserted at the tail of the queue, and the queue retrieval
20     * operations obtain elements at the head of the queue.
21 jsr166 1.29 * A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when
22 dl 1.19 * many threads will share access to a common collection.
23 dholmes 1.6 * This queue does not permit <tt>null</tt> elements.
24 dl 1.1 *
25 jsr166 1.29 * <p>This implementation employs an efficient &quot;wait-free&quot;
26 dholmes 1.6 * algorithm based on one described in <a
27 dl 1.1 * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
28     * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
29 dl 1.15 * Algorithms</a> by Maged M. Michael and Michael L. Scott.
30 dl 1.1 *
31 dholmes 1.7 * <p>Beware that, unlike in most collections, the <tt>size</tt> method
32 dl 1.1 * is <em>NOT</em> a constant-time operation. Because of the
33     * asynchronous nature of these queues, determining the current number
34 dl 1.15 * of elements requires a traversal of the elements.
35 dl 1.18 *
36 dl 1.27 * <p>This class and its iterator implement all of the
37     * <em>optional</em> methods of the {@link Collection} and {@link
38 jsr166 1.29 * Iterator} interfaces.
39 dl 1.18 *
40 dl 1.25 * <p>This class is a member of the
41     * <a href="{@docRoot}/../guide/collections/index.html">
42     * Java Collections Framework</a>.
43     *
44 dl 1.1 * @since 1.5
45     * @author Doug Lea
46 dl 1.21 * @param <E> the type of elements held in this collection
47 tim 1.2 *
48 dl 1.25 */
49 dl 1.1 public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
50     implements Queue<E>, java.io.Serializable {
51 dl 1.14 private static final long serialVersionUID = 196745693267521676L;
52 dl 1.1
53     /*
54     * This is a straight adaptation of Michael & Scott algorithm.
55     * For explanation, read the paper. The only (minor) algorithmic
56     * difference is that this version supports lazy deletion of
57     * internal nodes (method remove(Object)) -- remove CAS'es item
58     * fields to null. The normal queue operations unlink but then
59     * pass over nodes with null item fields. Similarly, iteration
60     * methods ignore those with nulls.
61     */
62    
63 dl 1.23 private static class Node<E> {
64 dl 1.22 private volatile E item;
65 dl 1.23 private volatile Node<E> next;
66 jsr166 1.29
67     private static final
68     AtomicReferenceFieldUpdater<Node, Node>
69 dl 1.13 nextUpdater =
70     AtomicReferenceFieldUpdater.newUpdater
71 dl 1.23 (Node.class, Node.class, "next");
72 jsr166 1.29 private static final
73     AtomicReferenceFieldUpdater<Node, Object>
74 dl 1.13 itemUpdater =
75     AtomicReferenceFieldUpdater.newUpdater
76 dl 1.23 (Node.class, Object.class, "item");
77 jsr166 1.29
78 dl 1.23 Node(E x) { item = x; }
79 jsr166 1.29
80 dl 1.23 Node(E x, Node<E> n) { item = x; next = n; }
81 jsr166 1.29
82 dl 1.22 E getItem() {
83 dl 1.13 return item;
84     }
85 jsr166 1.29
86 dl 1.22 boolean casItem(E cmp, E val) {
87 dl 1.13 return itemUpdater.compareAndSet(this, cmp, val);
88     }
89 jsr166 1.29
90 dl 1.22 void setItem(E val) {
91 dl 1.13 itemUpdater.set(this, val);
92     }
93 jsr166 1.29
94 dl 1.23 Node<E> getNext() {
95 dl 1.13 return next;
96     }
97 jsr166 1.29
98 dl 1.23 boolean casNext(Node<E> cmp, Node<E> val) {
99 dl 1.13 return nextUpdater.compareAndSet(this, cmp, val);
100     }
101 jsr166 1.29
102 dl 1.23 void setNext(Node<E> val) {
103 dl 1.13 nextUpdater.set(this, val);
104     }
105 jsr166 1.29
106 dl 1.13 }
107 dl 1.1
108 jsr166 1.29 private static final
109     AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
110     tailUpdater =
111 dl 1.5 AtomicReferenceFieldUpdater.newUpdater
112 dl 1.23 (ConcurrentLinkedQueue.class, Node.class, "tail");
113 jsr166 1.29 private static final
114     AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
115     headUpdater =
116 dl 1.5 AtomicReferenceFieldUpdater.newUpdater
117 dl 1.23 (ConcurrentLinkedQueue.class, Node.class, "head");
118 dl 1.1
119 dl 1.23 private boolean casTail(Node<E> cmp, Node<E> val) {
120 dl 1.1 return tailUpdater.compareAndSet(this, cmp, val);
121     }
122    
123 dl 1.23 private boolean casHead(Node<E> cmp, Node<E> val) {
124 dl 1.1 return headUpdater.compareAndSet(this, cmp, val);
125     }
126    
127    
128 tim 1.2 /**
129 dl 1.1 * Pointer to header node, initialized to a dummy node. The first
130     * actual node is at head.getNext().
131     */
132 dl 1.23 private transient volatile Node<E> head = new Node<E>(null, null);
133 dl 1.1
134     /** Pointer to last node on list **/
135 dl 1.23 private transient volatile Node<E> tail = head;
136 dl 1.1
137    
138     /**
139 dholmes 1.6 * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
140 dl 1.1 */
141     public ConcurrentLinkedQueue() {}
142    
143     /**
144 jsr166 1.29 * Creates a <tt>ConcurrentLinkedQueue</tt>
145 dholmes 1.7 * initially containing the elements of the given collection,
146 dholmes 1.6 * added in traversal order of the collection's iterator.
147     * @param c the collection of elements to initially contain
148     * @throws NullPointerException if <tt>c</tt> or any element within it
149 jsr166 1.29 * is <tt>null</tt>.
150 dl 1.1 */
151 dholmes 1.6 public ConcurrentLinkedQueue(Collection<? extends E> c) {
152     for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
153 dl 1.1 add(it.next());
154     }
155    
156 jsr166 1.29 // Have to override just to update the javadoc
157 dholmes 1.6
158     /**
159 dholmes 1.7 * Adds the specified element to the tail of this queue.
160     *
161 jsr166 1.32 * @return <tt>true</tt> (as per the spec for {@link Collection#add}).
162     * @throws NullPointerException if the specified element is null
163 dholmes 1.6 */
164 jsr166 1.31 public boolean add(E e) {
165     return offer(e);
166 dholmes 1.6 }
167    
168     /**
169 jsr166 1.32 * Inserts the specified element at the tail of this queue.
170 dl 1.17 *
171 jsr166 1.32 * @return <tt>true</tt> (as per the spec for {@link Queue#offer})
172     * @throws NullPointerException if the specified element is null
173 dholmes 1.6 */
174 jsr166 1.31 public boolean offer(E e) {
175     if (e == null) throw new NullPointerException();
176     Node<E> n = new Node<E>(e, null);
177 dl 1.1 for(;;) {
178 dl 1.23 Node<E> t = tail;
179     Node<E> s = t.getNext();
180 dl 1.1 if (t == tail) {
181     if (s == null) {
182     if (t.casNext(s, n)) {
183 tim 1.2 casTail(t, n);
184 dl 1.1 return true;
185     }
186 tim 1.12 } else {
187 dl 1.1 casTail(t, s);
188     }
189     }
190     }
191     }
192    
193     public E poll() {
194     for (;;) {
195 dl 1.23 Node<E> h = head;
196     Node<E> t = tail;
197     Node<E> first = h.getNext();
198 dl 1.1 if (h == head) {
199     if (h == t) {
200     if (first == null)
201     return null;
202     else
203     casTail(t, first);
204 tim 1.12 } else if (casHead(h, first)) {
205 dl 1.22 E item = first.getItem();
206 dl 1.1 if (item != null) {
207     first.setItem(null);
208     return item;
209     }
210 tim 1.2 // else skip over deleted item, continue loop,
211 dl 1.1 }
212     }
213     }
214     }
215    
216     public E peek() { // same as poll except don't remove item
217     for (;;) {
218 dl 1.23 Node<E> h = head;
219     Node<E> t = tail;
220     Node<E> first = h.getNext();
221 dl 1.1 if (h == head) {
222     if (h == t) {
223     if (first == null)
224     return null;
225     else
226     casTail(t, first);
227 tim 1.12 } else {
228 dl 1.22 E item = first.getItem();
229 dl 1.1 if (item != null)
230     return item;
231     else // remove deleted node and continue
232     casHead(h, first);
233     }
234     }
235     }
236     }
237    
238     /**
239 dholmes 1.6 * Returns the first actual (non-header) node on list. This is yet
240 dl 1.1 * another variant of poll/peek; here returning out the first
241     * node, not element (so we cannot collapse with peek() without
242     * introducing race.)
243     */
244 dl 1.23 Node<E> first() {
245 dl 1.1 for (;;) {
246 dl 1.23 Node<E> h = head;
247     Node<E> t = tail;
248     Node<E> first = h.getNext();
249 dl 1.1 if (h == head) {
250     if (h == t) {
251     if (first == null)
252     return null;
253     else
254     casTail(t, first);
255 tim 1.12 } else {
256 dl 1.1 if (first.getItem() != null)
257     return first;
258     else // remove deleted node and continue
259     casHead(h, first);
260     }
261     }
262     }
263     }
264    
265    
266 dl 1.28 /**
267 jsr166 1.30 * Returns <tt>true</tt> if this queue contains no elements.
268 dl 1.28 *
269 jsr166 1.30 * @return <tt>true</tt> if this queue contains no elements.
270 dl 1.28 */
271 dl 1.1 public boolean isEmpty() {
272     return first() == null;
273     }
274    
275     /**
276 dl 1.17 * Returns the number of elements in this queue. If this queue
277     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
278     * <tt>Integer.MAX_VALUE</tt>.
279 tim 1.2 *
280 dl 1.17 * <p>Beware that, unlike in most collections, this method is
281 dl 1.1 * <em>NOT</em> a constant-time operation. Because of the
282     * asynchronous nature of these queues, determining the current
283     * number of elements requires an O(n) traversal.
284 dl 1.17 *
285     * @return the number of elements in this queue.
286 tim 1.2 */
287 dl 1.1 public int size() {
288     int count = 0;
289 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
290 dl 1.8 if (p.getItem() != null) {
291     // Collections.size() spec says to max out
292     if (++count == Integer.MAX_VALUE)
293     break;
294     }
295 dl 1.1 }
296     return count;
297     }
298    
299 dholmes 1.6 public boolean contains(Object o) {
300     if (o == null) return false;
301 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
302 dl 1.22 E item = p.getItem();
303 tim 1.2 if (item != null &&
304 dholmes 1.6 o.equals(item))
305 dl 1.1 return true;
306     }
307     return false;
308     }
309    
310 dholmes 1.6 public boolean remove(Object o) {
311     if (o == null) return false;
312 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
313 dl 1.22 E item = p.getItem();
314 tim 1.2 if (item != null &&
315 dholmes 1.6 o.equals(item) &&
316 dl 1.1 p.casItem(item, null))
317     return true;
318     }
319     return false;
320     }
321 tim 1.2
322 dl 1.1 public Object[] toArray() {
323     // Use ArrayList to deal with resizing.
324 tim 1.3 ArrayList<E> al = new ArrayList<E>();
325 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
326 dl 1.22 E item = p.getItem();
327 dl 1.1 if (item != null)
328     al.add(item);
329     }
330     return al.toArray();
331     }
332    
333     public <T> T[] toArray(T[] a) {
334     // try to use sent-in array
335     int k = 0;
336 dl 1.23 Node<E> p;
337 dl 1.1 for (p = first(); p != null && k < a.length; p = p.getNext()) {
338 dl 1.22 E item = p.getItem();
339 dl 1.1 if (item != null)
340     a[k++] = (T)item;
341     }
342     if (p == null) {
343     if (k < a.length)
344     a[k] = null;
345     return a;
346     }
347    
348     // If won't fit, use ArrayList version
349 tim 1.3 ArrayList<E> al = new ArrayList<E>();
350 dl 1.23 for (Node<E> q = first(); q != null; q = q.getNext()) {
351 dl 1.22 E item = q.getItem();
352 dl 1.1 if (item != null)
353     al.add(item);
354     }
355     return (T[])al.toArray(a);
356     }
357    
358 dholmes 1.7 /**
359     * Returns an iterator over the elements in this queue in proper sequence.
360 dl 1.9 * The returned iterator is a "weakly consistent" iterator that
361 jsr166 1.29 * will never throw {@link ConcurrentModificationException},
362 dl 1.9 * and guarantees to traverse elements as they existed upon
363     * construction of the iterator, and may (but is not guaranteed to)
364     * reflect any modifications subsequent to construction.
365 dholmes 1.7 *
366     * @return an iterator over the elements in this queue in proper sequence.
367     */
368 dl 1.1 public Iterator<E> iterator() {
369     return new Itr();
370     }
371    
372     private class Itr implements Iterator<E> {
373     /**
374     * Next node to return item for.
375     */
376 dl 1.23 private Node<E> nextNode;
377 dl 1.1
378 tim 1.2 /**
379 dl 1.1 * nextItem holds on to item fields because once we claim
380     * that an element exists in hasNext(), we must return it in
381     * the following next() call even if it was in the process of
382     * being removed when hasNext() was called.
383 jsr166 1.29 */
384 dl 1.1 private E nextItem;
385    
386     /**
387     * Node of the last returned item, to support remove.
388     */
389 dl 1.23 private Node<E> lastRet;
390 dl 1.1
391 tim 1.2 Itr() {
392 dl 1.1 advance();
393     }
394 tim 1.2
395 dl 1.1 /**
396 dl 1.26 * Moves to next valid node and returns item to return for
397     * next(), or null if no such.
398 dl 1.1 */
399 tim 1.2 private E advance() {
400 dl 1.1 lastRet = nextNode;
401 dl 1.22 E x = nextItem;
402 dl 1.1
403 dl 1.23 Node<E> p = (nextNode == null)? first() : nextNode.getNext();
404 dl 1.1 for (;;) {
405     if (p == null) {
406     nextNode = null;
407     nextItem = null;
408     return x;
409     }
410 dl 1.22 E item = p.getItem();
411 dl 1.1 if (item != null) {
412     nextNode = p;
413     nextItem = item;
414     return x;
415 tim 1.12 } else // skip over nulls
416 dl 1.1 p = p.getNext();
417     }
418     }
419 tim 1.2
420 dl 1.1 public boolean hasNext() {
421     return nextNode != null;
422     }
423 tim 1.2
424 dl 1.1 public E next() {
425     if (nextNode == null) throw new NoSuchElementException();
426     return advance();
427     }
428 tim 1.2
429 dl 1.1 public void remove() {
430 dl 1.23 Node<E> l = lastRet;
431 dl 1.1 if (l == null) throw new IllegalStateException();
432     // rely on a future traversal to relink.
433     l.setItem(null);
434     lastRet = null;
435     }
436     }
437    
438     /**
439     * Save the state to a stream (that is, serialize it).
440     *
441     * @serialData All of the elements (each an <tt>E</tt>) in
442     * the proper order, followed by a null
443     * @param s the stream
444     */
445     private void writeObject(java.io.ObjectOutputStream s)
446     throws java.io.IOException {
447    
448     // Write out any hidden stuff
449     s.defaultWriteObject();
450 tim 1.2
451 dl 1.1 // Write out all elements in the proper order.
452 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
453 dl 1.1 Object item = p.getItem();
454     if (item != null)
455     s.writeObject(item);
456     }
457    
458     // Use trailing null as sentinel
459     s.writeObject(null);
460     }
461    
462     /**
463     * Reconstitute the Queue instance from a stream (that is,
464     * deserialize it).
465     * @param s the stream
466     */
467     private void readObject(java.io.ObjectInputStream s)
468     throws java.io.IOException, ClassNotFoundException {
469 tim 1.2 // Read in capacity, and any hidden stuff
470     s.defaultReadObject();
471 dl 1.23 head = new Node<E>(null, null);
472 dl 1.16 tail = head;
473 tim 1.2 // Read in all elements and place in queue
474 dl 1.1 for (;;) {
475     E item = (E)s.readObject();
476     if (item == null)
477     break;
478 dl 1.16 else
479     offer(item);
480 dl 1.1 }
481     }
482    
483     }