jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java
author dl
Tue, 28 Jul 2009 13:24:52 -0700
changeset 3414 cdf768813b4d
parent 2 90ce3da70b43
child 3419 3ae6dc68c20d
permissions -rw-r--r--
6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element 6493942: ConcurrentLinkedQueue.remove sometimes very slow Summary: new algorithm for handling concurrent linked lists Reviewed-by: martin
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
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    38
import java.util.AbstractQueue;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    39
import java.util.ArrayList;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    40
import java.util.Collection;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    41
import java.util.Iterator;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    42
import java.util.NoSuchElementException;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    43
import java.util.Queue;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * This queue orders elements FIFO (first-in-first-out).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * The <em>head</em> of the queue is that element that has been on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * queue the longest time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * The <em>tail</em> of the queue is that element that has been on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * queue the shortest time. New elements
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * are inserted at the tail of the queue, and the queue retrieval
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * operations obtain elements at the head of the queue.
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    54
 * A {@code ConcurrentLinkedQueue} is an appropriate choice when
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * many threads will share access to a common collection.
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    56
 * This queue does not permit {@code null} elements.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * <p>This implementation employs an efficient &quot;wait-free&quot;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * algorithm based on one described in <a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * href="http://www.cs.rochester.edu/u/michael/PODC96.html"> Simple,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * Algorithms</a> by Maged M. Michael and Michael L. Scott.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    64
 * <p>Beware that, unlike in most collections, the {@code size} method
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * is <em>NOT</em> a constant-time operation. Because of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * asynchronous nature of these queues, determining the current number
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * of elements requires a traversal of the elements.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * <p>This class and its iterator implement all of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * <em>optional</em> methods of the {@link Collection} and {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * Iterator} interfaces.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * <p>Memory consistency effects: As with other concurrent
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * collections, actions in a thread prior to placing an object into a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * {@code ConcurrentLinkedQueue}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * actions subsequent to the access or removal of that element from
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 * the {@code ConcurrentLinkedQueue} in another thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * <p>This class is a member of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * Java Collections Framework</a>.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
 * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * @author Doug Lea
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 * @param <E> the type of elements held in this collection
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        implements Queue<E>, java.io.Serializable {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    private static final long serialVersionUID = 196745693267521676L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    /*
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    94
     * This is a modification of the Michael & Scott algorithm,
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    95
     * adapted for a garbage-collected environment, with support for
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    96
     * interior node deletion (to support remove(Object)).  For
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    97
     * explanation, read the paper.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
    99
     * Note that like most non-blocking algorithms in this package,
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   100
     * this implementation relies on the fact that in garbage
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
     * collected systems, there is no possibility of ABA problems due
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
     * to recycled nodes, so there is no need to use "counted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
     * pointers" or related techniques seen in versions used in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
     * non-GC'ed settings.
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   105
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   106
     * The fundamental invariants are:
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   107
     * - There is exactly one (last) Node with a null next reference,
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   108
     *   which is CASed when enqueueing.  This last Node can be
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   109
     *   reached in O(1) time from tail, but tail is merely an
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   110
     *   optimization - it can always be reached in O(N) time from
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   111
     *   head as well.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   112
     * - The elements contained in the queue are the non-null items in
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   113
     *   Nodes that are reachable from head.  CASing the item
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   114
     *   reference of a Node to null atomically removes it from the
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   115
     *   queue.  Reachability of all elements from head must remain
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   116
     *   true even in the case of concurrent modifications that cause
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   117
     *   head to advance.  A dequeued Node may remain in use
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   118
     *   indefinitely due to creation of an Iterator or simply a
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   119
     *   poll() that has lost its time slice.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   120
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   121
     * The above might appear to imply that all Nodes are GC-reachable
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   122
     * from a predecessor dequeued Node.  That would cause two problems:
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   123
     * - allow a rogue Iterator to cause unbounded memory retention
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   124
     * - cause cross-generational linking of old Nodes to new Nodes if
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   125
     *   a Node was tenured while live, which generational GCs have a
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   126
     *   hard time dealing with, causing repeated major collections.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   127
     * However, only non-deleted Nodes need to be reachable from
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   128
     * dequeued Nodes, and reachability does not necessarily have to
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   129
     * be of the kind understood by the GC.  We use the trick of
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   130
     * linking a Node that has just been dequeued to itself.  Such a
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   131
     * self-link implicitly means to advance to head.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   132
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   133
     * Both head and tail are permitted to lag.  In fact, failing to
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   134
     * update them every time one could is a significant optimization
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   135
     * (fewer CASes). This is controlled by local "hops" variables
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   136
     * that only trigger helping-CASes after experiencing multiple
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   137
     * lags.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   138
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   139
     * Since head and tail are updated concurrently and independently,
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   140
     * it is possible for tail to lag behind head (why not)?
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   141
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   142
     * CASing a Node's item reference to null atomically removes the
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   143
     * element from the queue.  Iterators skip over Nodes with null
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   144
     * items.  Prior implementations of this class had a race between
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   145
     * poll() and remove(Object) where the same element would appear
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   146
     * to be successfully removed by two concurrent operations.  The
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   147
     * method remove(Object) also lazily unlinks deleted Nodes, but
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   148
     * this is merely an optimization.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   149
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   150
     * When constructing a Node (before enqueuing it) we avoid paying
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   151
     * for a volatile write to item by using lazySet instead of a
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   152
     * normal write.  This allows the cost of enqueue to be
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   153
     * "one-and-a-half" CASes.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   154
     *
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   155
     * Both head and tail may or may not point to a Node with a
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   156
     * non-null item.  If the queue is empty, all items must of course
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   157
     * be null.  Upon creation, both head and tail refer to a dummy
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   158
     * Node with null item.  Both head and tail are only updated using
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   159
     * CAS, so they never regress, although again this is merely an
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   160
     * optimization.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
    private static class Node<E> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        private volatile E item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        private volatile Node<E> next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   167
        Node(E item) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   168
            // Piggyback on imminent casNext()
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   169
            lazySetItem(item);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   170
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        E getItem() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
            return item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        boolean casItem(E cmp, E val) {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   177
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        void setItem(E val) {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   181
            item = val;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   182
        }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   183
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   184
        void lazySetItem(E val) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   185
            UNSAFE.putOrderedObject(this, itemOffset, val);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   186
        }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   187
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   188
        void lazySetNext(Node<E> val) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   189
            UNSAFE.putOrderedObject(this, nextOffset, val);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        Node<E> getNext() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
            return next;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
        boolean casNext(Node<E> cmp, Node<E> val) {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   197
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   200
        // Unsafe mechanics
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   202
        private static final sun.misc.Unsafe UNSAFE =
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   203
            sun.misc.Unsafe.getUnsafe();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   204
        private static final long nextOffset =
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   205
            objectFieldOffset(UNSAFE, "next", Node.class);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   206
        private static final long itemOffset =
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   207
            objectFieldOffset(UNSAFE, "item", Node.class);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   210
    /**
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   211
     * A node from which the first live (non-deleted) node (if any)
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   212
     * can be reached in O(1) time.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   213
     * Invariants:
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   214
     * - all live nodes are reachable from head via succ()
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   215
     * - head != null
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   216
     * - (tmp = head).next != tmp || tmp != head
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   217
     * Non-invariants:
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   218
     * - head.item may or may not be null.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   219
     * - it is permitted for tail to lag behind head, that is, for tail
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   220
     *   to not be reachable from head!
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   221
     */
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   222
    private transient volatile Node<E> head = new Node<E>(null);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   225
     * A node from which the last node on list (that is, the unique
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   226
     * node with node.next == null) can be reached in O(1) time.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   227
     * Invariants:
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   228
     * - the last node is always reachable from tail via succ()
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   229
     * - tail != null
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   230
     * Non-invariants:
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   231
     * - tail.item may or may not be null.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   232
     * - it is permitted for tail to lag behind head, that is, for tail
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   233
     *   to not be reachable from head!
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   234
     * - tail.next may or may not be self-pointing to tail.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    private transient volatile Node<E> tail = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   240
     * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
    public ConcurrentLinkedQueue() {}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   245
     * Creates a {@code ConcurrentLinkedQueue}
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
     * initially containing the elements of the given collection,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
     * added in traversal order of the collection's iterator.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
     * @param c the collection of elements to initially contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
     * @throws NullPointerException if the specified collection or any
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     *         of its elements are null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    public ConcurrentLinkedQueue(Collection<? extends E> c) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
            add(it.next());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    // Have to override just to update the javadoc
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     * Inserts the specified element at the tail of this queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   262
     * @return {@code true} (as specified by {@link Collection#add})
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
     * @throws NullPointerException if the specified element is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    public boolean add(E e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        return offer(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   270
     * We don't bother to update head or tail pointers if fewer than
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   271
     * HOPS links from "true" location.  We assume that volatile
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   272
     * writes are significantly more expensive than volatile reads.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   273
     */
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   274
    private static final int HOPS = 1;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   275
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   276
    /**
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   277
     * Try to CAS head to p. If successful, repoint old head to itself
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   278
     * as sentinel for succ(), below.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   279
     */
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   280
    final void updateHead(Node<E> h, Node<E> p) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   281
        if (h != p && casHead(h, p))
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   282
            h.lazySetNext(h);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   283
    }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   284
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   285
    /**
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   286
     * Returns the successor of p, or the head node if p.next has been
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   287
     * linked to self, which will only be true if traversing with a
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   288
     * stale pointer that is now off the list.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   289
     */
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   290
    final Node<E> succ(Node<E> p) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   291
        Node<E> next = p.getNext();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   292
        return (p == next) ? head : next;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   293
    }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   294
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   295
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
     * Inserts the specified element at the tail of this queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   298
     * @return {@code true} (as specified by {@link Queue#offer})
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
     * @throws NullPointerException if the specified element is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
    public boolean offer(E e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
        if (e == null) throw new NullPointerException();
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   303
        Node<E> n = new Node<E>(e);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   304
        retry:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            Node<E> t = tail;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   307
            Node<E> p = t;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   308
            for (int hops = 0; ; hops++) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   309
                Node<E> next = succ(p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   310
                if (next != null) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   311
                    if (hops > HOPS && t != tail)
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   312
                        continue retry;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   313
                    p = next;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   314
                } else if (p.casNext(null, n)) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   315
                    if (hops >= HOPS)
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   316
                        casTail(t, n);  // Failure is OK.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   317
                    return true;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                } else {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   319
                    p = succ(p);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    public E poll() {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   326
        Node<E> h = head;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   327
        Node<E> p = h;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   328
        for (int hops = 0; ; hops++) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   329
            E item = p.getItem();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   330
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   331
            if (item != null && p.casItem(item, null)) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   332
                if (hops >= HOPS) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   333
                    Node<E> q = p.getNext();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   334
                    updateHead(h, (q != null) ? q : p);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
                }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   336
                return item;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   338
            Node<E> next = succ(p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   339
            if (next == null) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   340
                updateHead(h, p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   341
                break;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   342
            }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   343
            p = next;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   345
        return null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   348
    public E peek() {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   349
        Node<E> h = head;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   350
        Node<E> p = h;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   351
        E item;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        for (;;) {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   353
            item = p.getItem();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   354
            if (item != null)
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   355
                break;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   356
            Node<E> next = succ(p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   357
            if (next == null) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   358
                break;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
            }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   360
            p = next;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   362
        updateHead(h, p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   363
        return item;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   367
     * Returns the first live (non-deleted) node on list, or null if none.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   368
     * This is yet another variant of poll/peek; here returning the
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   369
     * first node, not element.  We could make peek() a wrapper around
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   370
     * first(), but that would cost an extra volatile read of item,
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   371
     * and the need to add a retry loop to deal with the possibility
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   372
     * of losing a race to a concurrent poll().
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
    Node<E> first() {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   375
        Node<E> h = head;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   376
        Node<E> p = h;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   377
        Node<E> result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
        for (;;) {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   379
            E item = p.getItem();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   380
            if (item != null) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   381
                result = p;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   382
                break;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   384
            Node<E> next = succ(p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   385
            if (next == null) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   386
                result = null;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   387
                break;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   388
            }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   389
            p = next;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        }
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   391
        updateHead(h, p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   392
        return result;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   396
     * Returns {@code true} if this queue contains no elements.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   398
     * @return {@code true} if this queue contains no elements
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
    public boolean isEmpty() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
        return first() == null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
     * Returns the number of elements in this queue.  If this queue
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   406
     * contains more than {@code Integer.MAX_VALUE} elements, returns
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   407
     * {@code Integer.MAX_VALUE}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
     * <p>Beware that, unlike in most collections, this method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
     * <em>NOT</em> a constant-time operation. Because of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
     * asynchronous nature of these queues, determining the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
     * number of elements requires an O(n) traversal.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
     * @return the number of elements in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
    public int size() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        int count = 0;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   418
        for (Node<E> p = first(); p != null; p = succ(p)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            if (p.getItem() != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                // Collections.size() spec says to max out
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                if (++count == Integer.MAX_VALUE)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
        return count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
    /**
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   429
     * Returns {@code true} if this queue contains the specified element.
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   430
     * More formally, returns {@code true} if and only if this queue contains
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   431
     * at least one element {@code e} such that {@code o.equals(e)}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
     * @param o object to be checked for containment in this queue
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   434
     * @return {@code true} if this queue contains the specified element
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    public boolean contains(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        if (o == null) return false;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   438
        for (Node<E> p = first(); p != null; p = succ(p)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
            if (item != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                o.equals(item))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
     * Removes a single instance of the specified element from this queue,
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   449
     * if it is present.  More formally, removes an element {@code e} such
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   450
     * that {@code o.equals(e)}, if this queue contains one or more such
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
     * elements.
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   452
     * Returns {@code true} if this queue contained the specified element
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
     * (or equivalently, if this queue changed as a result of the call).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
     * @param o element to be removed from this queue, if present
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   456
     * @return {@code true} if this queue changed as a result of the call
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
    public boolean remove(Object o) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
        if (o == null) return false;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   460
        Node<E> pred = null;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   461
        for (Node<E> p = first(); p != null; p = succ(p)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
            if (item != null &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                o.equals(item) &&
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   465
                p.casItem(item, null)) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   466
                Node<E> next = succ(p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   467
                if (pred != null && next != null)
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   468
                    pred.casNext(p, next);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                return true;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   470
            }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   471
            pred = p;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     * Returns an array containing all of the elements in this queue, in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
     * proper sequence.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
     * <p>The returned array will be "safe" in that no references to it are
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
     * maintained by this queue.  (In other words, this method must allocate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
     * a new array).  The caller is thus free to modify the returned array.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     * <p>This method acts as bridge between array-based and collection-based
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     * APIs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     * @return an array containing all of the elements in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
    public Object[] toArray() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        // Use ArrayList to deal with resizing.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        ArrayList<E> al = new ArrayList<E>();
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   492
        for (Node<E> p = first(); p != null; p = succ(p)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                al.add(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        return al.toArray();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
     * Returns an array containing all of the elements in this queue, in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
     * proper sequence; the runtime type of the returned array is that of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
     * the specified array.  If the queue fits in the specified array, it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
     * is returned therein.  Otherwise, a new array is allocated with the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
     * runtime type of the specified array and the size of this queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
     * <p>If this queue fits in the specified array with room to spare
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
     * (i.e., the array has more elements than this queue), the element in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
     * the array immediately following the end of the queue is set to
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   510
     * {@code null}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
     * <p>Like the {@link #toArray()} method, this method acts as bridge between
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
     * array-based and collection-based APIs.  Further, this method allows
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
     * precise control over the runtime type of the output array, and may,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
     * under certain circumstances, be used to save allocation costs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   517
     * <p>Suppose {@code x} is a queue known to contain only strings.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
     * The following code can be used to dump the queue into a newly
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   519
     * allocated array of {@code String}:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
     * <pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
     *     String[] y = x.toArray(new String[0]);</pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   524
     * Note that {@code toArray(new Object[0])} is identical in function to
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   525
     * {@code toArray()}.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
     * @param a the array into which the elements of the queue are to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
     *          be stored, if it is big enough; otherwise, a new array of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
     *          same runtime type is allocated for this purpose
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
     * @return an array containing all of the elements in this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
     * @throws ArrayStoreException if the runtime type of the specified array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     *         is not a supertype of the runtime type of every element in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
     *         this queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
     * @throws NullPointerException if the specified array is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
     */
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   536
    @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    public <T> T[] toArray(T[] a) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        // try to use sent-in array
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
        int k = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        Node<E> p;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   541
        for (p = first(); p != null && k < a.length; p = succ(p)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                a[k++] = (T)item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        if (p == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            if (k < a.length)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                a[k] = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            return a;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
        // If won't fit, use ArrayList version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        ArrayList<E> al = new ArrayList<E>();
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   554
        for (Node<E> q = first(); q != null; q = succ(q)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            E item = q.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
                al.add(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
        return al.toArray(a);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
     * Returns an iterator over the elements in this queue in proper sequence.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
     * The returned iterator is a "weakly consistent" iterator that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
     * will never throw {@link ConcurrentModificationException},
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
     * and guarantees to traverse elements as they existed upon
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
     * construction of the iterator, and may (but is not guaranteed to)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
     * reflect any modifications subsequent to construction.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
     * @return an iterator over the elements in this queue in proper sequence
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
    public Iterator<E> iterator() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        return new Itr();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
    private class Itr implements Iterator<E> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
         * Next node to return item for.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        private Node<E> nextNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
         * nextItem holds on to item fields because once we claim
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
         * that an element exists in hasNext(), we must return it in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
         * the following next() call even if it was in the process of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
         * being removed when hasNext() was called.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        private E nextItem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
         * Node of the last returned item, to support remove.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
        private Node<E> lastRet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        Itr() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
            advance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
         * Moves to next valid node and returns item to return for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
         * next(), or null if no such.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        private E advance() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
            lastRet = nextNode;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
            E x = nextItem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   607
            Node<E> pred, p;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   608
            if (nextNode == null) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   609
                p = first();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   610
                pred = null;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   611
            } else {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   612
                pred = nextNode;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   613
                p = succ(nextNode);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   614
            }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   615
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
            for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
                if (p == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
                    nextNode = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
                    nextItem = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
                    return x;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
                E item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
                if (item != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
                    nextNode = p;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
                    nextItem = item;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
                    return x;
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   627
                } else {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   628
                    // skip over nulls
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   629
                    Node<E> next = succ(p);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   630
                    if (pred != null && next != null)
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   631
                        pred.casNext(p, next);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   632
                    p = next;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   633
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
        public boolean hasNext() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
            return nextNode != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        public E next() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
            if (nextNode == null) throw new NoSuchElementException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            return advance();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
        public void remove() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
            Node<E> l = lastRet;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
            if (l == null) throw new IllegalStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
            // rely on a future traversal to relink.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            l.setItem(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
            lastRet = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
     * Save the state to a stream (that is, serialize it).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
     *
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   658
     * @serialData All of the elements (each an {@code E}) in
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
     * the proper order, followed by a null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
     * @param s the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
    private void writeObject(java.io.ObjectOutputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
        throws java.io.IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        // Write out any hidden stuff
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
        s.defaultWriteObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
        // Write out all elements in the proper order.
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   669
        for (Node<E> p = first(); p != null; p = succ(p)) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            Object item = p.getItem();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            if (item != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                s.writeObject(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
        // Use trailing null as sentinel
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        s.writeObject(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
     * Reconstitute the Queue instance from a stream (that is,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
     * deserialize it).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
     * @param s the stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
    private void readObject(java.io.ObjectInputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        throws java.io.IOException, ClassNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        // Read in capacity, and any hidden stuff
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        s.defaultReadObject();
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   688
        head = new Node<E>(null);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
        tail = head;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
        // Read in all elements and place in queue
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        for (;;) {
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   692
            @SuppressWarnings("unchecked")
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            E item = (E)s.readObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
            if (item == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
            else
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
                offer(item);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
3414
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   701
    // Unsafe mechanics
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   702
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   703
    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   704
    private static final long headOffset =
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   705
        objectFieldOffset(UNSAFE, "head", ConcurrentLinkedQueue.class);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   706
    private static final long tailOffset =
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   707
        objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedQueue.class);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   708
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   709
    private boolean casTail(Node<E> cmp, Node<E> val) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   710
        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   711
    }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   712
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   713
    private boolean casHead(Node<E> cmp, Node<E> val) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   714
        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   715
    }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   716
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   717
    private void lazySetHead(Node<E> val) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   718
        UNSAFE.putOrderedObject(this, headOffset, val);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   719
    }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   720
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   721
    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   722
                                  String field, Class<?> klazz) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   723
        try {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   724
            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   725
        } catch (NoSuchFieldException e) {
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   726
            // Convert Exception to corresponding Error
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   727
            NoSuchFieldError error = new NoSuchFieldError(field);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   728
            error.initCause(e);
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   729
            throw error;
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   730
        }
cdf768813b4d 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element
dl
parents: 2
diff changeset
   731
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
}