ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentLinkedQueue.java
Revision: 1.39
Committed: Mon Jul 18 19:14:17 2005 UTC (18 years, 10 months ago) by jsr166
Branch: MAIN
Changes since 1.38: +2 -2 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 jsr166 1.34 * @throws NullPointerException if the specified collection or any
149     * of its elements are null
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 jsr166 1.35 * Inserts the specified element at the tail of this queue.
160 dholmes 1.7 *
161 jsr166 1.39 * @return <tt>true</tt> (as specified by {@link Collection#add})
162 jsr166 1.32 * @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.39 * @return <tt>true</tt> (as specified by {@link Queue#offer})
172 jsr166 1.32 * @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 jsr166 1.38 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.33 * @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 jsr166 1.37 * @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 jsr166 1.37 /**
300     * Returns <tt>true</tt> if this queue contains the specified element.
301     * More formally, returns <tt>true</tt> if and only if this queue contains
302     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
303     *
304     * @param o object to be checked for containment in this queue
305     * @return <tt>true</tt> if this queue contains the specified element
306     */
307 dholmes 1.6 public boolean contains(Object o) {
308     if (o == null) return false;
309 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
310 dl 1.22 E item = p.getItem();
311 tim 1.2 if (item != null &&
312 dholmes 1.6 o.equals(item))
313 dl 1.1 return true;
314     }
315     return false;
316     }
317    
318 jsr166 1.37 /**
319     * Removes a single instance of the specified element from this queue,
320     * if it is present. More formally, removes an element <tt>e</tt> such
321     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
322     * elements.
323     * Returns <tt>true</tt> if this queue contained the specified element
324     * (or equivalently, if this queue changed as a result of the call).
325     *
326     * @param o element to be removed from this queue, if present
327     * @return <tt>true</tt> if this queue changed as a result of the call
328     */
329 dholmes 1.6 public boolean remove(Object o) {
330     if (o == null) return false;
331 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
332 dl 1.22 E item = p.getItem();
333 tim 1.2 if (item != null &&
334 dholmes 1.6 o.equals(item) &&
335 dl 1.1 p.casItem(item, null))
336     return true;
337     }
338     return false;
339     }
340 tim 1.2
341 jsr166 1.33 /**
342     * Returns an array containing all of the elements in this queue, in
343     * proper sequence.
344     *
345     * <p>The returned array will be "safe" in that no references to it are
346     * maintained by this queue. (In other words, this method must allocate
347     * a new array). The caller is thus free to modify the returned array.
348 jsr166 1.36 *
349 jsr166 1.33 * <p>This method acts as bridge between array-based and collection-based
350     * APIs.
351     *
352     * @return an array containing all of the elements in this queue
353     */
354 dl 1.1 public Object[] toArray() {
355     // Use ArrayList to deal with resizing.
356 tim 1.3 ArrayList<E> al = new ArrayList<E>();
357 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
358 dl 1.22 E item = p.getItem();
359 dl 1.1 if (item != null)
360     al.add(item);
361     }
362     return al.toArray();
363     }
364    
365 jsr166 1.33 /**
366     * Returns an array containing all of the elements in this queue, in
367     * proper sequence; the runtime type of the returned array is that of
368     * the specified array. If the queue fits in the specified array, it
369     * is returned therein. Otherwise, a new array is allocated with the
370     * runtime type of the specified array and the size of this queue.
371     *
372     * <p>If this queue fits in the specified array with room to spare
373     * (i.e., the array has more elements than this queue), the element in
374     * the array immediately following the end of the queue is set to
375     * <tt>null</tt>.
376     *
377     * <p>Like the {@link #toArray()} method, this method acts as bridge between
378     * array-based and collection-based APIs. Further, this method allows
379     * precise control over the runtime type of the output array, and may,
380     * under certain circumstances, be used to save allocation costs.
381     *
382     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
383     * The following code can be used to dump the queue into a newly
384     * allocated array of <tt>String</tt>:
385     *
386     * <pre>
387     * String[] y = x.toArray(new String[0]);</pre>
388     *
389     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
390     * <tt>toArray()</tt>.
391     *
392     * @param a the array into which the elements of the queue are to
393     * be stored, if it is big enough; otherwise, a new array of the
394     * same runtime type is allocated for this purpose
395     * @return an array containing all of the elements in this queue
396     * @throws ArrayStoreException if the runtime type of the specified array
397     * is not a supertype of the runtime type of every element in
398     * this queue
399     * @throws NullPointerException if the specified array is null
400     */
401 dl 1.1 public <T> T[] toArray(T[] a) {
402     // try to use sent-in array
403     int k = 0;
404 dl 1.23 Node<E> p;
405 dl 1.1 for (p = first(); p != null && k < a.length; p = p.getNext()) {
406 dl 1.22 E item = p.getItem();
407 dl 1.1 if (item != null)
408     a[k++] = (T)item;
409     }
410     if (p == null) {
411     if (k < a.length)
412     a[k] = null;
413     return a;
414     }
415    
416     // If won't fit, use ArrayList version
417 tim 1.3 ArrayList<E> al = new ArrayList<E>();
418 dl 1.23 for (Node<E> q = first(); q != null; q = q.getNext()) {
419 dl 1.22 E item = q.getItem();
420 dl 1.1 if (item != null)
421     al.add(item);
422     }
423     return (T[])al.toArray(a);
424     }
425    
426 dholmes 1.7 /**
427     * Returns an iterator over the elements in this queue in proper sequence.
428 dl 1.9 * The returned iterator is a "weakly consistent" iterator that
429 jsr166 1.29 * will never throw {@link ConcurrentModificationException},
430 dl 1.9 * and guarantees to traverse elements as they existed upon
431     * construction of the iterator, and may (but is not guaranteed to)
432     * reflect any modifications subsequent to construction.
433 dholmes 1.7 *
434 jsr166 1.33 * @return an iterator over the elements in this queue in proper sequence
435 dholmes 1.7 */
436 dl 1.1 public Iterator<E> iterator() {
437     return new Itr();
438     }
439    
440     private class Itr implements Iterator<E> {
441     /**
442     * Next node to return item for.
443     */
444 dl 1.23 private Node<E> nextNode;
445 dl 1.1
446 tim 1.2 /**
447 dl 1.1 * nextItem holds on to item fields because once we claim
448     * that an element exists in hasNext(), we must return it in
449     * the following next() call even if it was in the process of
450     * being removed when hasNext() was called.
451 jsr166 1.29 */
452 dl 1.1 private E nextItem;
453    
454     /**
455     * Node of the last returned item, to support remove.
456     */
457 dl 1.23 private Node<E> lastRet;
458 dl 1.1
459 tim 1.2 Itr() {
460 dl 1.1 advance();
461     }
462 tim 1.2
463 dl 1.1 /**
464 dl 1.26 * Moves to next valid node and returns item to return for
465     * next(), or null if no such.
466 dl 1.1 */
467 tim 1.2 private E advance() {
468 dl 1.1 lastRet = nextNode;
469 dl 1.22 E x = nextItem;
470 dl 1.1
471 dl 1.23 Node<E> p = (nextNode == null)? first() : nextNode.getNext();
472 dl 1.1 for (;;) {
473     if (p == null) {
474     nextNode = null;
475     nextItem = null;
476     return x;
477     }
478 dl 1.22 E item = p.getItem();
479 dl 1.1 if (item != null) {
480     nextNode = p;
481     nextItem = item;
482     return x;
483 tim 1.12 } else // skip over nulls
484 dl 1.1 p = p.getNext();
485     }
486     }
487 tim 1.2
488 dl 1.1 public boolean hasNext() {
489     return nextNode != null;
490     }
491 tim 1.2
492 dl 1.1 public E next() {
493     if (nextNode == null) throw new NoSuchElementException();
494     return advance();
495     }
496 tim 1.2
497 dl 1.1 public void remove() {
498 dl 1.23 Node<E> l = lastRet;
499 dl 1.1 if (l == null) throw new IllegalStateException();
500     // rely on a future traversal to relink.
501     l.setItem(null);
502     lastRet = null;
503     }
504     }
505    
506     /**
507     * Save the state to a stream (that is, serialize it).
508     *
509     * @serialData All of the elements (each an <tt>E</tt>) in
510     * the proper order, followed by a null
511     * @param s the stream
512     */
513     private void writeObject(java.io.ObjectOutputStream s)
514     throws java.io.IOException {
515    
516     // Write out any hidden stuff
517     s.defaultWriteObject();
518 tim 1.2
519 dl 1.1 // Write out all elements in the proper order.
520 dl 1.23 for (Node<E> p = first(); p != null; p = p.getNext()) {
521 dl 1.1 Object item = p.getItem();
522     if (item != null)
523     s.writeObject(item);
524     }
525    
526     // Use trailing null as sentinel
527     s.writeObject(null);
528     }
529    
530     /**
531     * Reconstitute the Queue instance from a stream (that is,
532     * deserialize it).
533     * @param s the stream
534     */
535     private void readObject(java.io.ObjectInputStream s)
536     throws java.io.IOException, ClassNotFoundException {
537 tim 1.2 // Read in capacity, and any hidden stuff
538     s.defaultReadObject();
539 dl 1.23 head = new Node<E>(null, null);
540 dl 1.16 tail = head;
541 tim 1.2 // Read in all elements and place in queue
542 dl 1.1 for (;;) {
543     E item = (E)s.readObject();
544     if (item == null)
545     break;
546 dl 1.16 else
547     offer(item);
548 dl 1.1 }
549     }
550    
551     }