jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 3414 cdf768813b4d
permissions -rw-r--r--
Initial load
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * under the terms of the GNU General Public License version 2 only, as
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * published by the Free Software Foundation.  Sun designates this
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * particular file as subject to the "Classpath" exception as provided
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * by Sun in the LICENSE file that accompanied this code.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    21
 * CA 95054 USA or visit www.sun.com if you need additional information or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    22
 * have any questions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * This file is available under and governed by the GNU General Public
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * License version 2 only, as published by the Free Software Foundation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * However, the following notice accompanied the original version of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * file:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * Written by Doug Lea with assistance from members of JCP JSR-166
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * Expert Group and released to the public domain, as explained at
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
 * http://creativecommons.org/licenses/publicdomain
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
package java.util.concurrent;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import java.util.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import java.util.concurrent.atomic.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * This queue orders elements FIFO (first-in-first-out).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * The <em>head</em> of the queue is that element that has been on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * queue the longest time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * The <em>tail</em> of the queue is that element that has been on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * queue the shortest time. New elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * are inserted at the tail of the queue, and the queue retrieval
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * operations obtain elements at the head of the queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * many threads will share access to a common collection.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * This queue does not permit <tt>null</tt> elements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * <p>This implementation employs an efficient &quot;wait-free&quot;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * algorithm based on one described in <a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * Algorithms</a> by Maged M. Michael and Michael L. Scott.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * <p>Beware that, unlike in most collections, the <tt>size</tt> method
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * is <em>NOT</em> a constant-time operation. Because of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * asynchronous nature of these queues, determining the current number
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * of elements requires a traversal of the elements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * <p>This class and its iterator implement all of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * <em>optional</em> methods of the {@link Collection} and {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * Iterator} interfaces.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * <p>Memory consistency effects: As with other concurrent
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * collections, actions in a thread prior to placing an object into a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * {@code ConcurrentLinkedQueue}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * actions subsequent to the access or removal of that element from
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * the {@code ConcurrentLinkedQueue} in another thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * <p>This class is a member of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * Java Collections Framework</a>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * @author Doug Lea
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * @param <E> the type of elements held in this collection
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
        implements Queue<E>, java.io.Serializable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private static final long serialVersionUID = 196745693267521676L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
     * This is a straight adaptation of Michael & Scott algorithm.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
     * For explanation, read the paper.  The only (minor) algorithmic
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
     * difference is that this version supports lazy deletion of
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
     * internal nodes (method remove(Object)) -- remove CAS'es item
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
     * fields to null. The normal queue operations unlink but then
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
     * pass over nodes with null item fields. Similarly, iteration
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
     * methods ignore those with nulls.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     * Also note that like most non-blocking algorithms in this
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
     * package, this implementation relies on the fact that in garbage
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
     * collected systems, there is no possibility of ABA problems due
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     * to recycled nodes, so there is no need to use "counted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     * pointers" or related techniques seen in versions used in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * non-GC'ed settings.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    private static class Node<E> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
        private volatile E item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
        private volatile Node<E> next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
        private static final
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
            AtomicReferenceFieldUpdater<Node, Node>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
            nextUpdater =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            AtomicReferenceFieldUpdater.newUpdater
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
            (Node.class, Node.class, "next");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
        private static final
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
            AtomicReferenceFieldUpdater<Node, Object>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
            itemUpdater =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
            AtomicReferenceFieldUpdater.newUpdater
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
            (Node.class, Object.class, "item");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
        Node(E x) { item = x; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        Node(E x, Node<E> n) { item = x; next = n; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        E getItem() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
            return item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
        boolean casItem(E cmp, E val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
            return itemUpdater.compareAndSet(this, cmp, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
        void setItem(E val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
            itemUpdater.set(this, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
        Node<E> getNext() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
            return next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        boolean casNext(Node<E> cmp, Node<E> val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
            return nextUpdater.compareAndSet(this, cmp, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
        void setNext(Node<E> val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
            nextUpdater.set(this, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    private static final
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        tailUpdater =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        AtomicReferenceFieldUpdater.newUpdater
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        (ConcurrentLinkedQueue.class, Node.class, "tail");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    private static final
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        headUpdater =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        AtomicReferenceFieldUpdater.newUpdater
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        (ConcurrentLinkedQueue.class,  Node.class, "head");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    private boolean casTail(Node<E> cmp, Node<E> val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        return tailUpdater.compareAndSet(this, cmp, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    private boolean casHead(Node<E> cmp, Node<E> val) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
        return headUpdater.compareAndSet(this, cmp, val);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * Pointer to header node, initialized to a dummy node.  The first
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
     * actual node is at head.getNext().
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
    private transient volatile Node<E> head = new Node<E>(null, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
    /** Pointer to last node on list **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    private transient volatile Node<E> tail = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
     * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
    public ConcurrentLinkedQueue() {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
     * Creates a <tt>ConcurrentLinkedQueue</tt>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
     * initially containing the elements of the given collection,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
     * added in traversal order of the collection's iterator.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
     * @param c the collection of elements to initially contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
     * @throws NullPointerException if the specified collection or any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
     *         of its elements are null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    public ConcurrentLinkedQueue(Collection<? extends E> c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
            add(it.next());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    // Have to override just to update the javadoc
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
     * Inserts the specified element at the tail of this queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
     * @return <tt>true</tt> (as specified by {@link Collection#add})
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
     * @throws NullPointerException if the specified element is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    public boolean add(E e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        return offer(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * Inserts the specified element at the tail of this queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
     * @return <tt>true</tt> (as specified by {@link Queue#offer})
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
     * @throws NullPointerException if the specified element is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    public boolean offer(E e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        if (e == null) throw new NullPointerException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        Node<E> n = new Node<E>(e, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            Node<E> t = tail;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            Node<E> s = t.getNext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            if (t == tail) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                if (s == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                    if (t.casNext(s, n)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
                        casTail(t, n);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                    casTail(t, s);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    public E poll() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
            Node<E> h = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
            Node<E> t = tail;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
            Node<E> first = h.getNext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
            if (h == head) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                if (h == t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                    if (first == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                    else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                        casTail(t, first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                } else if (casHead(h, first)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                    E item = first.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                    if (item != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                        first.setItem(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                        return item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                    // else skip over deleted item, continue loop,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    public E peek() { // same as poll except don't remove item
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
        for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            Node<E> h = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
            Node<E> t = tail;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            Node<E> first = h.getNext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
            if (h == head) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                if (h == t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                    if (first == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
                    else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
                        casTail(t, first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
                    E item = first.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
                    if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
                        return item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
                    else // remove deleted node and continue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
                        casHead(h, first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
     * Returns the first actual (non-header) node on list.  This is yet
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
     * another variant of poll/peek; here returning out the first
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
     * node, not element (so we cannot collapse with peek() without
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
     * introducing race.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    Node<E> first() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            Node<E> h = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
            Node<E> t = tail;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
            Node<E> first = h.getNext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
            if (h == head) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
                if (h == t) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                    if (first == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
                        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
                    else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
                        casTail(t, first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
                    if (first.getItem() != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
                        return first;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
                    else // remove deleted node and continue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                        casHead(h, first);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
     * Returns <tt>true</tt> if this queue contains no elements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
     * @return <tt>true</tt> if this queue contains no elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    public boolean isEmpty() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        return first() == null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
     * Returns the number of elements in this queue.  If this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
     * <tt>Integer.MAX_VALUE</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
     * <p>Beware that, unlike in most collections, this method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
     * <em>NOT</em> a constant-time operation. Because of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
     * asynchronous nature of these queues, determining the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     * number of elements requires an O(n) traversal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     * @return the number of elements in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    public int size() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
        int count = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        for (Node<E> p = first(); p != null; p = p.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
            if (p.getItem() != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
                // Collections.size() spec says to max out
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                if (++count == Integer.MAX_VALUE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
        return count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
     * Returns <tt>true</tt> if this queue contains the specified element.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
     * More formally, returns <tt>true</tt> if and only if this queue contains
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
     * @param o object to be checked for containment in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
     * @return <tt>true</tt> if this queue contains the specified element
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    public boolean contains(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        if (o == null) return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        for (Node<E> p = first(); p != null; p = p.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
            if (item != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                o.equals(item))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
     * Removes a single instance of the specified element from this queue,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
     * if it is present.  More formally, removes an element <tt>e</tt> such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
     * elements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
     * Returns <tt>true</tt> if this queue contained the specified element
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
     * (or equivalently, if this queue changed as a result of the call).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
     * @param o element to be removed from this queue, if present
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
     * @return <tt>true</tt> if this queue changed as a result of the call
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
    public boolean remove(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        if (o == null) return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        for (Node<E> p = first(); p != null; p = p.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
            if (item != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
                o.equals(item) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
                p.casItem(item, null))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
     * Returns an array containing all of the elements in this queue, in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
     * proper sequence.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
     * <p>The returned array will be "safe" in that no references to it are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
     * maintained by this queue.  (In other words, this method must allocate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
     * a new array).  The caller is thus free to modify the returned array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
     * <p>This method acts as bridge between array-based and collection-based
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
     * APIs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
     * @return an array containing all of the elements in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
    public Object[] toArray() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        // Use ArrayList to deal with resizing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        ArrayList<E> al = new ArrayList<E>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        for (Node<E> p = first(); p != null; p = p.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                al.add(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        return al.toArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
     * Returns an array containing all of the elements in this queue, in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
     * proper sequence; the runtime type of the returned array is that of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
     * the specified array.  If the queue fits in the specified array, it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
     * is returned therein.  Otherwise, a new array is allocated with the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
     * runtime type of the specified array and the size of this queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
     * <p>If this queue fits in the specified array with room to spare
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
     * (i.e., the array has more elements than this queue), the element in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
     * the array immediately following the end of the queue is set to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
     * <tt>null</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
     * <p>Like the {@link #toArray()} method, this method acts as bridge between
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
     * array-based and collection-based APIs.  Further, this method allows
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
     * precise control over the runtime type of the output array, and may,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
     * under certain circumstances, be used to save allocation costs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
     * The following code can be used to dump the queue into a newly
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     * allocated array of <tt>String</tt>:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
     *     String[] y = x.toArray(new String[0]);</pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
     * <tt>toArray()</tt>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
     * @param a the array into which the elements of the queue are to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
     *          be stored, if it is big enough; otherwise, a new array of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
     *          same runtime type is allocated for this purpose
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
     * @return an array containing all of the elements in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
     * @throws ArrayStoreException if the runtime type of the specified array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
     *         is not a supertype of the runtime type of every element in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
     *         this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
     * @throws NullPointerException if the specified array is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
    public <T> T[] toArray(T[] a) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        // try to use sent-in array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
        int k = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
        Node<E> p;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
        for (p = first(); p != null && k < a.length; p = p.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                a[k++] = (T)item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        if (p == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
            if (k < a.length)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                a[k] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
            return a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        // If won't fit, use ArrayList version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        ArrayList<E> al = new ArrayList<E>();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
        for (Node<E> q = first(); q != null; q = q.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            E item = q.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                al.add(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        return al.toArray(a);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
     * Returns an iterator over the elements in this queue in proper sequence.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
     * The returned iterator is a "weakly consistent" iterator that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
     * will never throw {@link ConcurrentModificationException},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
     * and guarantees to traverse elements as they existed upon
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
     * construction of the iterator, and may (but is not guaranteed to)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
     * reflect any modifications subsequent to construction.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * @return an iterator over the elements in this queue in proper sequence
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
    public Iterator<E> iterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
        return new Itr();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    private class Itr implements Iterator<E> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
         * Next node to return item for.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
        private Node<E> nextNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
         * nextItem holds on to item fields because once we claim
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
         * that an element exists in hasNext(), we must return it in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
         * the following next() call even if it was in the process of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
         * being removed when hasNext() was called.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        private E nextItem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
         * Node of the last returned item, to support remove.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
        private Node<E> lastRet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        Itr() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
            advance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
         * Moves to next valid node and returns item to return for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
         * next(), or null if no such.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        private E advance() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
            lastRet = nextNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            E x = nextItem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
            Node<E> p = (nextNode == null)? first() : nextNode.getNext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
                if (p == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                    nextNode = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
                    nextItem = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                    return x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
                E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                if (item != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
                    nextNode = p;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
                    nextItem = item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
                    return x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                } else // skip over nulls
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
                    p = p.getNext();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
        public boolean hasNext() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
            return nextNode != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        public E next() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
            if (nextNode == null) throw new NoSuchElementException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
            return advance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        public void remove() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
            Node<E> l = lastRet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            if (l == null) throw new IllegalStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            // rely on a future traversal to relink.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
            l.setItem(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            lastRet = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
     * Save the state to a stream (that is, serialize it).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
     * @serialData All of the elements (each an <tt>E</tt>) in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
     * the proper order, followed by a null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
     * @param s the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
    private void writeObject(java.io.ObjectOutputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
        throws java.io.IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        // Write out any hidden stuff
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
        s.defaultWriteObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        // Write out all elements in the proper order.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        for (Node<E> p = first(); p != null; p = p.getNext()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
            Object item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
                s.writeObject(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        // Use trailing null as sentinel
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        s.writeObject(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
     * Reconstitute the Queue instance from a stream (that is,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
     * deserialize it).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
     * @param s the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
    private void readObject(java.io.ObjectInputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
        throws java.io.IOException, ClassNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        // Read in capacity, and any hidden stuff
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        s.defaultReadObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        head = new Node<E>(null, null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
        tail = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
        // Read in all elements and place in queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
        for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
            E item = (E)s.readObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            if (item == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
                offer(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
}