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