jdk/src/share/classes/java/util/concurrent/LinkedTransferQueue.java
author dl
Thu, 07 Apr 2011 15:06:32 +0100
changeset 9242 ef138d47df58
parent 8544 225896f7b33c
child 9515 04056ec0f477
permissions -rw-r--r--
7034657: Update Creative Commons license URL in legal notices Reviewed-by: chegar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     1
/*
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     3
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     4
 * This code is free software; you can redistribute it and/or modify it
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     5
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
     6
 * published by the Free Software Foundation.  Oracle designates this
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     7
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
     8
 * by Oracle in the LICENSE file that accompanied this code.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
     9
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    13
 * version 2 for more details (a copy is included in the LICENSE file that
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    14
 * accompanied this code).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    15
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    16
 * You should have received a copy of the GNU General Public License version
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    19
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
    21
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4110
diff changeset
    22
 * questions.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    23
 */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    24
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    25
/*
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    26
 * This file is available under and governed by the GNU General Public
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    27
 * License version 2 only, as published by the Free Software Foundation.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    28
 * However, the following notice accompanied the original version of this
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    29
 * file:
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    30
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    31
 * Written by Doug Lea with assistance from members of JCP JSR-166
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    32
 * Expert Group and released to the public domain, as explained at
9242
ef138d47df58 7034657: Update Creative Commons license URL in legal notices
dl
parents: 8544
diff changeset
    33
 * http://creativecommons.org/publicdomain/zero/1.0/
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    34
 */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    35
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    36
package java.util.concurrent;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    37
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    38
import java.util.AbstractQueue;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    39
import java.util.Collection;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    40
import java.util.Iterator;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    41
import java.util.NoSuchElementException;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    42
import java.util.Queue;
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
    43
import java.util.concurrent.TimeUnit;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    44
import java.util.concurrent.locks.LockSupport;
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
    45
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    46
/**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    47
 * An unbounded {@link TransferQueue} based on linked nodes.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    48
 * This queue orders elements FIFO (first-in-first-out) with respect
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    49
 * to any given producer.  The <em>head</em> of the queue is that
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    50
 * element that has been on the queue the longest time for some
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    51
 * producer.  The <em>tail</em> of the queue is that element that has
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    52
 * been on the queue the shortest time for some producer.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    53
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    54
 * <p>Beware that, unlike in most collections, the {@code size}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    55
 * method is <em>NOT</em> a constant-time operation. Because of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    56
 * asynchronous nature of these queues, determining the current number
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    57
 * of elements requires a traversal of the elements.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    58
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    59
 * <p>This class and its iterator implement all of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    60
 * <em>optional</em> methods of the {@link Collection} and {@link
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    61
 * Iterator} interfaces.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    62
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    63
 * <p>Memory consistency effects: As with other concurrent
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    64
 * collections, actions in a thread prior to placing an object into a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    65
 * {@code LinkedTransferQueue}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    66
 * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    67
 * actions subsequent to the access or removal of that element from
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    68
 * the {@code LinkedTransferQueue} in another thread.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    69
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    70
 * <p>This class is a member of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    71
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    72
 * Java Collections Framework</a>.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    73
 *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    74
 * @since 1.7
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    75
 * @author Doug Lea
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    76
 * @param <E> the type of elements held in this collection
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    77
 */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    78
public class LinkedTransferQueue<E> extends AbstractQueue<E>
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    79
    implements TransferQueue<E>, java.io.Serializable {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    80
    private static final long serialVersionUID = -3223113410248163686L;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    81
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    82
    /*
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    83
     * *** Overview of Dual Queues with Slack ***
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    84
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    85
     * Dual Queues, introduced by Scherer and Scott
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    86
     * (http://www.cs.rice.edu/~wns1/papers/2004-DISC-DDS.pdf) are
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    87
     * (linked) queues in which nodes may represent either data or
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    88
     * requests.  When a thread tries to enqueue a data node, but
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    89
     * encounters a request node, it instead "matches" and removes it;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    90
     * and vice versa for enqueuing requests. Blocking Dual Queues
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    91
     * arrange that threads enqueuing unmatched requests block until
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    92
     * other threads provide the match. Dual Synchronous Queues (see
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    93
     * Scherer, Lea, & Scott
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    94
     * http://www.cs.rochester.edu/u/scott/papers/2009_Scherer_CACM_SSQ.pdf)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    95
     * additionally arrange that threads enqueuing unmatched data also
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    96
     * block.  Dual Transfer Queues support all of these modes, as
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    97
     * dictated by callers.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    98
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
    99
     * A FIFO dual queue may be implemented using a variation of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   100
     * Michael & Scott (M&S) lock-free queue algorithm
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   101
     * (http://www.cs.rochester.edu/u/scott/papers/1996_PODC_queues.pdf).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   102
     * It maintains two pointer fields, "head", pointing to a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   103
     * (matched) node that in turn points to the first actual
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   104
     * (unmatched) queue node (or null if empty); and "tail" that
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   105
     * points to the last node on the queue (or again null if
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   106
     * empty). For example, here is a possible queue with four data
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   107
     * elements:
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   108
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   109
     *  head                tail
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   110
     *    |                   |
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   111
     *    v                   v
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   112
     *    M -> U -> U -> U -> U
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   113
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   114
     * The M&S queue algorithm is known to be prone to scalability and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   115
     * overhead limitations when maintaining (via CAS) these head and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   116
     * tail pointers. This has led to the development of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   117
     * contention-reducing variants such as elimination arrays (see
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   118
     * Moir et al http://portal.acm.org/citation.cfm?id=1074013) and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   119
     * optimistic back pointers (see Ladan-Mozes & Shavit
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   120
     * http://people.csail.mit.edu/edya/publications/OptimisticFIFOQueue-journal.pdf).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   121
     * However, the nature of dual queues enables a simpler tactic for
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   122
     * improving M&S-style implementations when dual-ness is needed.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   123
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   124
     * In a dual queue, each node must atomically maintain its match
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   125
     * status. While there are other possible variants, we implement
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   126
     * this here as: for a data-mode node, matching entails CASing an
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   127
     * "item" field from a non-null data value to null upon match, and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   128
     * vice-versa for request nodes, CASing from null to a data
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   129
     * value. (Note that the linearization properties of this style of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   130
     * queue are easy to verify -- elements are made available by
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   131
     * linking, and unavailable by matching.) Compared to plain M&S
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   132
     * queues, this property of dual queues requires one additional
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   133
     * successful atomic operation per enq/deq pair. But it also
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   134
     * enables lower cost variants of queue maintenance mechanics. (A
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   135
     * variation of this idea applies even for non-dual queues that
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   136
     * support deletion of interior elements, such as
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   137
     * j.u.c.ConcurrentLinkedQueue.)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   138
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   139
     * Once a node is matched, its match status can never again
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   140
     * change.  We may thus arrange that the linked list of them
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   141
     * contain a prefix of zero or more matched nodes, followed by a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   142
     * suffix of zero or more unmatched nodes. (Note that we allow
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   143
     * both the prefix and suffix to be zero length, which in turn
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   144
     * means that we do not use a dummy header.)  If we were not
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   145
     * concerned with either time or space efficiency, we could
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   146
     * correctly perform enqueue and dequeue operations by traversing
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   147
     * from a pointer to the initial node; CASing the item of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   148
     * first unmatched node on match and CASing the next field of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   149
     * trailing node on appends. (Plus some special-casing when
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   150
     * initially empty).  While this would be a terrible idea in
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   151
     * itself, it does have the benefit of not requiring ANY atomic
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   152
     * updates on head/tail fields.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   153
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   154
     * We introduce here an approach that lies between the extremes of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   155
     * never versus always updating queue (head and tail) pointers.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   156
     * This offers a tradeoff between sometimes requiring extra
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   157
     * traversal steps to locate the first and/or last unmatched
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   158
     * nodes, versus the reduced overhead and contention of fewer
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   159
     * updates to queue pointers. For example, a possible snapshot of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   160
     * a queue is:
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   161
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   162
     *  head           tail
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   163
     *    |              |
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   164
     *    v              v
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   165
     *    M -> M -> U -> U -> U -> U
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   166
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   167
     * The best value for this "slack" (the targeted maximum distance
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   168
     * between the value of "head" and the first unmatched node, and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   169
     * similarly for "tail") is an empirical matter. We have found
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   170
     * that using very small constants in the range of 1-3 work best
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   171
     * over a range of platforms. Larger values introduce increasing
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   172
     * costs of cache misses and risks of long traversal chains, while
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   173
     * smaller values increase CAS contention and overhead.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   174
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   175
     * Dual queues with slack differ from plain M&S dual queues by
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   176
     * virtue of only sometimes updating head or tail pointers when
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   177
     * matching, appending, or even traversing nodes; in order to
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   178
     * maintain a targeted slack.  The idea of "sometimes" may be
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   179
     * operationalized in several ways. The simplest is to use a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   180
     * per-operation counter incremented on each traversal step, and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   181
     * to try (via CAS) to update the associated queue pointer
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   182
     * whenever the count exceeds a threshold. Another, that requires
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   183
     * more overhead, is to use random number generators to update
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   184
     * with a given probability per traversal step.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   185
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   186
     * In any strategy along these lines, because CASes updating
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   187
     * fields may fail, the actual slack may exceed targeted
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   188
     * slack. However, they may be retried at any time to maintain
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   189
     * targets.  Even when using very small slack values, this
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   190
     * approach works well for dual queues because it allows all
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   191
     * operations up to the point of matching or appending an item
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   192
     * (hence potentially allowing progress by another thread) to be
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   193
     * read-only, thus not introducing any further contention. As
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   194
     * described below, we implement this by performing slack
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   195
     * maintenance retries only after these points.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   196
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   197
     * As an accompaniment to such techniques, traversal overhead can
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   198
     * be further reduced without increasing contention of head
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   199
     * pointer updates: Threads may sometimes shortcut the "next" link
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   200
     * path from the current "head" node to be closer to the currently
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   201
     * known first unmatched node, and similarly for tail. Again, this
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   202
     * may be triggered with using thresholds or randomization.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   203
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   204
     * These ideas must be further extended to avoid unbounded amounts
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   205
     * of costly-to-reclaim garbage caused by the sequential "next"
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   206
     * links of nodes starting at old forgotten head nodes: As first
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   207
     * described in detail by Boehm
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   208
     * (http://portal.acm.org/citation.cfm?doid=503272.503282) if a GC
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   209
     * delays noticing that any arbitrarily old node has become
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   210
     * garbage, all newer dead nodes will also be unreclaimed.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   211
     * (Similar issues arise in non-GC environments.)  To cope with
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   212
     * this in our implementation, upon CASing to advance the head
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   213
     * pointer, we set the "next" link of the previous head to point
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   214
     * only to itself; thus limiting the length of connected dead lists.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   215
     * (We also take similar care to wipe out possibly garbage
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   216
     * retaining values held in other Node fields.)  However, doing so
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   217
     * adds some further complexity to traversal: If any "next"
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   218
     * pointer links to itself, it indicates that the current thread
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   219
     * has lagged behind a head-update, and so the traversal must
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   220
     * continue from the "head".  Traversals trying to find the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   221
     * current tail starting from "tail" may also encounter
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   222
     * self-links, in which case they also continue at "head".
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   223
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   224
     * It is tempting in slack-based scheme to not even use CAS for
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   225
     * updates (similarly to Ladan-Mozes & Shavit). However, this
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   226
     * cannot be done for head updates under the above link-forgetting
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   227
     * mechanics because an update may leave head at a detached node.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   228
     * And while direct writes are possible for tail updates, they
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   229
     * increase the risk of long retraversals, and hence long garbage
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   230
     * chains, which can be much more costly than is worthwhile
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   231
     * considering that the cost difference of performing a CAS vs
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   232
     * write is smaller when they are not triggered on each operation
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   233
     * (especially considering that writes and CASes equally require
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   234
     * additional GC bookkeeping ("write barriers") that are sometimes
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   235
     * more costly than the writes themselves because of contention).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   236
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   237
     * *** Overview of implementation ***
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   238
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   239
     * We use a threshold-based approach to updates, with a slack
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   240
     * threshold of two -- that is, we update head/tail when the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   241
     * current pointer appears to be two or more steps away from the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   242
     * first/last node. The slack value is hard-wired: a path greater
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   243
     * than one is naturally implemented by checking equality of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   244
     * traversal pointers except when the list has only one element,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   245
     * in which case we keep slack threshold at one. Avoiding tracking
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   246
     * explicit counts across method calls slightly simplifies an
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   247
     * already-messy implementation. Using randomization would
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   248
     * probably work better if there were a low-quality dirt-cheap
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   249
     * per-thread one available, but even ThreadLocalRandom is too
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   250
     * heavy for these purposes.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   251
     *
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   252
     * With such a small slack threshold value, it is not worthwhile
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   253
     * to augment this with path short-circuiting (i.e., unsplicing
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   254
     * interior nodes) except in the case of cancellation/removal (see
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   255
     * below).
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   256
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   257
     * We allow both the head and tail fields to be null before any
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   258
     * nodes are enqueued; initializing upon first append.  This
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   259
     * simplifies some other logic, as well as providing more
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   260
     * efficient explicit control paths instead of letting JVMs insert
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   261
     * implicit NullPointerExceptions when they are null.  While not
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   262
     * currently fully implemented, we also leave open the possibility
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   263
     * of re-nulling these fields when empty (which is complicated to
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   264
     * arrange, for little benefit.)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   265
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   266
     * All enqueue/dequeue operations are handled by the single method
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   267
     * "xfer" with parameters indicating whether to act as some form
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   268
     * of offer, put, poll, take, or transfer (each possibly with
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   269
     * timeout). The relative complexity of using one monolithic
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   270
     * method outweighs the code bulk and maintenance problems of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   271
     * using separate methods for each case.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   272
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   273
     * Operation consists of up to three phases. The first is
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   274
     * implemented within method xfer, the second in tryAppend, and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   275
     * the third in method awaitMatch.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   276
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   277
     * 1. Try to match an existing node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   278
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   279
     *    Starting at head, skip already-matched nodes until finding
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   280
     *    an unmatched node of opposite mode, if one exists, in which
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   281
     *    case matching it and returning, also if necessary updating
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   282
     *    head to one past the matched node (or the node itself if the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   283
     *    list has no other unmatched nodes). If the CAS misses, then
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   284
     *    a loop retries advancing head by two steps until either
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   285
     *    success or the slack is at most two. By requiring that each
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   286
     *    attempt advances head by two (if applicable), we ensure that
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   287
     *    the slack does not grow without bound. Traversals also check
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   288
     *    if the initial head is now off-list, in which case they
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   289
     *    start at the new head.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   290
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   291
     *    If no candidates are found and the call was untimed
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   292
     *    poll/offer, (argument "how" is NOW) return.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   293
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   294
     * 2. Try to append a new node (method tryAppend)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   295
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   296
     *    Starting at current tail pointer, find the actual last node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   297
     *    and try to append a new node (or if head was null, establish
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   298
     *    the first node). Nodes can be appended only if their
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   299
     *    predecessors are either already matched or are of the same
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   300
     *    mode. If we detect otherwise, then a new node with opposite
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   301
     *    mode must have been appended during traversal, so we must
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   302
     *    restart at phase 1. The traversal and update steps are
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   303
     *    otherwise similar to phase 1: Retrying upon CAS misses and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   304
     *    checking for staleness.  In particular, if a self-link is
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   305
     *    encountered, then we can safely jump to a node on the list
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   306
     *    by continuing the traversal at current head.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   307
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   308
     *    On successful append, if the call was ASYNC, return.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   309
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   310
     * 3. Await match or cancellation (method awaitMatch)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   311
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   312
     *    Wait for another thread to match node; instead cancelling if
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   313
     *    the current thread was interrupted or the wait timed out. On
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   314
     *    multiprocessors, we use front-of-queue spinning: If a node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   315
     *    appears to be the first unmatched node in the queue, it
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   316
     *    spins a bit before blocking. In either case, before blocking
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   317
     *    it tries to unsplice any nodes between the current "head"
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   318
     *    and the first unmatched node.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   319
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   320
     *    Front-of-queue spinning vastly improves performance of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   321
     *    heavily contended queues. And so long as it is relatively
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   322
     *    brief and "quiet", spinning does not much impact performance
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   323
     *    of less-contended queues.  During spins threads check their
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   324
     *    interrupt status and generate a thread-local random number
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   325
     *    to decide to occasionally perform a Thread.yield. While
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   326
     *    yield has underdefined specs, we assume that might it help,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   327
     *    and will not hurt in limiting impact of spinning on busy
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   328
     *    systems.  We also use smaller (1/2) spins for nodes that are
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   329
     *    not known to be front but whose predecessors have not
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   330
     *    blocked -- these "chained" spins avoid artifacts of
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   331
     *    front-of-queue rules which otherwise lead to alternating
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   332
     *    nodes spinning vs blocking. Further, front threads that
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   333
     *    represent phase changes (from data to request node or vice
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   334
     *    versa) compared to their predecessors receive additional
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   335
     *    chained spins, reflecting longer paths typically required to
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   336
     *    unblock threads during phase changes.
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   337
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   338
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   339
     * ** Unlinking removed interior nodes **
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   340
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   341
     * In addition to minimizing garbage retention via self-linking
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   342
     * described above, we also unlink removed interior nodes. These
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   343
     * may arise due to timed out or interrupted waits, or calls to
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   344
     * remove(x) or Iterator.remove.  Normally, given a node that was
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   345
     * at one time known to be the predecessor of some node s that is
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   346
     * to be removed, we can unsplice s by CASing the next field of
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   347
     * its predecessor if it still points to s (otherwise s must
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   348
     * already have been removed or is now offlist). But there are two
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   349
     * situations in which we cannot guarantee to make node s
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   350
     * unreachable in this way: (1) If s is the trailing node of list
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   351
     * (i.e., with null next), then it is pinned as the target node
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   352
     * for appends, so can only be removed later after other nodes are
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   353
     * appended. (2) We cannot necessarily unlink s given a
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   354
     * predecessor node that is matched (including the case of being
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   355
     * cancelled): the predecessor may already be unspliced, in which
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   356
     * case some previous reachable node may still point to s.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   357
     * (For further explanation see Herlihy & Shavit "The Art of
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   358
     * Multiprocessor Programming" chapter 9).  Although, in both
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   359
     * cases, we can rule out the need for further action if either s
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   360
     * or its predecessor are (or can be made to be) at, or fall off
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   361
     * from, the head of list.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   362
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   363
     * Without taking these into account, it would be possible for an
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   364
     * unbounded number of supposedly removed nodes to remain
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   365
     * reachable.  Situations leading to such buildup are uncommon but
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   366
     * can occur in practice; for example when a series of short timed
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   367
     * calls to poll repeatedly time out but never otherwise fall off
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   368
     * the list because of an untimed call to take at the front of the
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   369
     * queue.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   370
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   371
     * When these cases arise, rather than always retraversing the
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   372
     * entire list to find an actual predecessor to unlink (which
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   373
     * won't help for case (1) anyway), we record a conservative
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   374
     * estimate of possible unsplice failures (in "sweepVotes").
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   375
     * We trigger a full sweep when the estimate exceeds a threshold
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   376
     * ("SWEEP_THRESHOLD") indicating the maximum number of estimated
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   377
     * removal failures to tolerate before sweeping through, unlinking
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   378
     * cancelled nodes that were not unlinked upon initial removal.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   379
     * We perform sweeps by the thread hitting threshold (rather than
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   380
     * background threads or by spreading work to other threads)
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   381
     * because in the main contexts in which removal occurs, the
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   382
     * caller is already timed-out, cancelled, or performing a
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   383
     * potentially O(n) operation (e.g. remove(x)), none of which are
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   384
     * time-critical enough to warrant the overhead that alternatives
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   385
     * would impose on other threads.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   386
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   387
     * Because the sweepVotes estimate is conservative, and because
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   388
     * nodes become unlinked "naturally" as they fall off the head of
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   389
     * the queue, and because we allow votes to accumulate even while
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   390
     * sweeps are in progress, there are typically significantly fewer
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   391
     * such nodes than estimated.  Choice of a threshold value
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   392
     * balances the likelihood of wasted effort and contention, versus
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   393
     * providing a worst-case bound on retention of interior nodes in
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   394
     * quiescent queues. The value defined below was chosen
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   395
     * empirically to balance these under various timeout scenarios.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   396
     *
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   397
     * Note that we cannot self-link unlinked interior nodes during
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   398
     * sweeps. However, the associated garbage chains terminate when
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   399
     * some successor ultimately falls off the head of the list and is
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   400
     * self-linked.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   401
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   402
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   403
    /** True if on multiprocessor */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   404
    private static final boolean MP =
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   405
        Runtime.getRuntime().availableProcessors() > 1;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   406
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   407
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   408
     * The number of times to spin (with randomly interspersed calls
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   409
     * to Thread.yield) on multiprocessor before blocking when a node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   410
     * is apparently the first waiter in the queue.  See above for
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   411
     * explanation. Must be a power of two. The value is empirically
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   412
     * derived -- it works pretty well across a variety of processors,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   413
     * numbers of CPUs, and OSes.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   414
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   415
    private static final int FRONT_SPINS   = 1 << 7;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   416
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   417
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   418
     * The number of times to spin before blocking when a node is
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   419
     * preceded by another node that is apparently spinning.  Also
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   420
     * serves as an increment to FRONT_SPINS on phase changes, and as
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   421
     * base average frequency for yielding during spins. Must be a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   422
     * power of two.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   423
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   424
    private static final int CHAINED_SPINS = FRONT_SPINS >>> 1;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   425
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   426
    /**
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   427
     * The maximum number of estimated removal failures (sweepVotes)
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   428
     * to tolerate before sweeping through the queue unlinking
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   429
     * cancelled nodes that were not unlinked upon initial
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   430
     * removal. See above for explanation. The value must be at least
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   431
     * two to avoid useless sweeps when removing trailing nodes.
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   432
     */
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   433
    static final int SWEEP_THRESHOLD = 32;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   434
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   435
    /**
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   436
     * Queue nodes. Uses Object, not E, for items to allow forgetting
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   437
     * them after use.  Relies heavily on Unsafe mechanics to minimize
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   438
     * unnecessary ordering constraints: Writes that are intrinsically
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   439
     * ordered wrt other accesses or CASes use simple relaxed forms.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   440
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   441
    static final class Node {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   442
        final boolean isData;   // false if this is a request node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   443
        volatile Object item;   // initially non-null if isData; CASed to match
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   444
        volatile Node next;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   445
        volatile Thread waiter; // null until waiting
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   446
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   447
        // CAS methods for fields
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   448
        final boolean casNext(Node cmp, Node val) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   449
            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   450
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   451
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   452
        final boolean casItem(Object cmp, Object val) {
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   453
            // assert cmp == null || cmp.getClass() != Node.class;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   454
            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   455
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   456
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   457
        /**
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   458
         * Constructs a new node.  Uses relaxed write because item can
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   459
         * only be seen after publication via casNext.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   460
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   461
        Node(Object item, boolean isData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   462
            UNSAFE.putObject(this, itemOffset, item); // relaxed write
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   463
            this.isData = isData;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   464
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   465
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   466
        /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   467
         * Links node to itself to avoid garbage retention.  Called
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   468
         * only after CASing head field, so uses relaxed write.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   469
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   470
        final void forgetNext() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   471
            UNSAFE.putObject(this, nextOffset, this);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   472
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   473
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   474
        /**
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   475
         * Sets item to self and waiter to null, to avoid garbage
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   476
         * retention after matching or cancelling. Uses relaxed writes
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   477
         * because order is already constrained in the only calling
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   478
         * contexts: item is forgotten only after volatile/atomic
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   479
         * mechanics that extract items.  Similarly, clearing waiter
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   480
         * follows either CAS or return from park (if ever parked;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   481
         * else we don't care).
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   482
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   483
        final void forgetContents() {
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   484
            UNSAFE.putObject(this, itemOffset, this);
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   485
            UNSAFE.putObject(this, waiterOffset, null);
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   486
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   487
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   488
        /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   489
         * Returns true if this node has been matched, including the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   490
         * case of artificial matches due to cancellation.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   491
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   492
        final boolean isMatched() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   493
            Object x = item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   494
            return (x == this) || ((x == null) == isData);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   495
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   496
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   497
        /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   498
         * Returns true if this is an unmatched request node.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   499
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   500
        final boolean isUnmatchedRequest() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   501
            return !isData && item == null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   502
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   503
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   504
        /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   505
         * Returns true if a node with the given mode cannot be
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   506
         * appended to this node because this node is unmatched and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   507
         * has opposite data mode.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   508
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   509
        final boolean cannotPrecede(boolean haveData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   510
            boolean d = isData;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   511
            Object x;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   512
            return d != haveData && (x = item) != this && (x != null) == d;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   513
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   514
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   515
        /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   516
         * Tries to artificially match a data node -- used by remove.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   517
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   518
        final boolean tryMatchData() {
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   519
            // assert isData;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   520
            Object x = item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   521
            if (x != null && x != this && casItem(x, null)) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   522
                LockSupport.unpark(waiter);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   523
                return true;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   524
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   525
            return false;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   526
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   527
8544
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   528
        private static final long serialVersionUID = -3375979862319811754L;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   529
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   530
        // Unsafe mechanics
8544
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   531
        private static final sun.misc.Unsafe UNSAFE;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   532
        private static final long itemOffset;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   533
        private static final long nextOffset;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   534
        private static final long waiterOffset;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   535
        static {
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   536
            try {
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   537
                UNSAFE = sun.misc.Unsafe.getUnsafe();
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   538
                Class k = Node.class;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   539
                itemOffset = UNSAFE.objectFieldOffset
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   540
                    (k.getDeclaredField("item"));
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   541
                nextOffset = UNSAFE.objectFieldOffset
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   542
                    (k.getDeclaredField("next"));
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   543
                waiterOffset = UNSAFE.objectFieldOffset
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   544
                    (k.getDeclaredField("waiter"));
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   545
            } catch (Exception e) {
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   546
                throw new Error(e);
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   547
            }
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
   548
        }
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   549
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   550
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   551
    /** head of the queue; null until first enqueue */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   552
    transient volatile Node head;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   553
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   554
    /** tail of the queue; null until first append */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   555
    private transient volatile Node tail;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   556
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   557
    /** The number of apparent failures to unsplice removed nodes */
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   558
    private transient volatile int sweepVotes;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   559
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   560
    // CAS methods for fields
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   561
    private boolean casTail(Node cmp, Node val) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   562
        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   563
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   564
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   565
    private boolean casHead(Node cmp, Node val) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   566
        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   567
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   568
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   569
    private boolean casSweepVotes(int cmp, int val) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   570
        return UNSAFE.compareAndSwapInt(this, sweepVotesOffset, cmp, val);
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   571
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   572
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   573
    /*
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   574
     * Possible values for "how" argument in xfer method.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   575
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   576
    private static final int NOW   = 0; // for untimed poll, tryTransfer
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   577
    private static final int ASYNC = 1; // for offer, put, add
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   578
    private static final int SYNC  = 2; // for transfer, take
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   579
    private static final int TIMED = 3; // for timed poll, tryTransfer
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   580
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   581
    @SuppressWarnings("unchecked")
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   582
    static <E> E cast(Object item) {
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   583
        // assert item == null || item.getClass() != Node.class;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   584
        return (E) item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   585
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   586
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   587
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   588
     * Implements all queuing methods. See above for explanation.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   589
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   590
     * @param e the item or null for take
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   591
     * @param haveData true if this is a put, else a take
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   592
     * @param how NOW, ASYNC, SYNC, or TIMED
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   593
     * @param nanos timeout in nanosecs, used only if mode is TIMED
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   594
     * @return an item if matched, else e
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   595
     * @throws NullPointerException if haveData mode but e is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   596
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   597
    private E xfer(E e, boolean haveData, int how, long nanos) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   598
        if (haveData && (e == null))
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   599
            throw new NullPointerException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   600
        Node s = null;                        // the node to append, if needed
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   601
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   602
        retry:
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   603
        for (;;) {                            // restart on append race
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   604
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   605
            for (Node h = head, p = h; p != null;) { // find & match first node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   606
                boolean isData = p.isData;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   607
                Object item = p.item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   608
                if (item != p && (item != null) == isData) { // unmatched
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   609
                    if (isData == haveData)   // can't match
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   610
                        break;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   611
                    if (p.casItem(item, e)) { // match
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   612
                        for (Node q = p; q != h;) {
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   613
                            Node n = q.next;  // update by 2 unless singleton
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   614
                            if (head == h && casHead(h, n == null ? q : n)) {
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   615
                                h.forgetNext();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   616
                                break;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   617
                            }                 // advance and retry
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   618
                            if ((h = head)   == null ||
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   619
                                (q = h.next) == null || !q.isMatched())
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   620
                                break;        // unless slack < 2
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   621
                        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   622
                        LockSupport.unpark(p.waiter);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   623
                        return this.<E>cast(item);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   624
                    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   625
                }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   626
                Node n = p.next;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   627
                p = (p != n) ? n : (h = head); // Use head if p offlist
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   628
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   629
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   630
            if (how != NOW) {                 // No matches available
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   631
                if (s == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   632
                    s = new Node(e, haveData);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   633
                Node pred = tryAppend(s, haveData);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   634
                if (pred == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   635
                    continue retry;           // lost race vs opposite mode
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   636
                if (how != ASYNC)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   637
                    return awaitMatch(s, pred, e, (how == TIMED), nanos);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   638
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   639
            return e; // not waiting
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   640
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   641
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   642
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   643
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   644
     * Tries to append node s as tail.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   645
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   646
     * @param s the node to append
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   647
     * @param haveData true if appending in data mode
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   648
     * @return null on failure due to losing race with append in
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   649
     * different mode, else s's predecessor, or s itself if no
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   650
     * predecessor
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   651
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   652
    private Node tryAppend(Node s, boolean haveData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   653
        for (Node t = tail, p = t;;) {        // move p to last node and append
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   654
            Node n, u;                        // temps for reads of next & tail
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   655
            if (p == null && (p = head) == null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   656
                if (casHead(null, s))
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   657
                    return s;                 // initialize
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   658
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   659
            else if (p.cannotPrecede(haveData))
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   660
                return null;                  // lost race vs opposite mode
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   661
            else if ((n = p.next) != null)    // not last; keep traversing
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   662
                p = p != t && t != (u = tail) ? (t = u) : // stale tail
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   663
                    (p != n) ? n : null;      // restart if off list
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   664
            else if (!p.casNext(null, s))
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   665
                p = p.next;                   // re-read on CAS failure
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   666
            else {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   667
                if (p != t) {                 // update if slack now >= 2
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   668
                    while ((tail != t || !casTail(t, s)) &&
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   669
                           (t = tail)   != null &&
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   670
                           (s = t.next) != null && // advance and retry
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   671
                           (s = s.next) != null && s != t);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   672
                }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   673
                return p;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   674
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   675
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   676
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   677
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   678
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   679
     * Spins/yields/blocks until node s is matched or caller gives up.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   680
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   681
     * @param s the waiting node
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   682
     * @param pred the predecessor of s, or s itself if it has no
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   683
     * predecessor, or null if unknown (the null case does not occur
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   684
     * in any current calls but may in possible future extensions)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   685
     * @param e the comparison value for checking match
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   686
     * @param timed if true, wait only until timeout elapses
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   687
     * @param nanos timeout in nanosecs, used only if timed is true
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   688
     * @return matched item, or e if unmatched on interrupt or timeout
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   689
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   690
    private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   691
        long lastTime = timed ? System.nanoTime() : 0L;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   692
        Thread w = Thread.currentThread();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   693
        int spins = -1; // initialized after first item and cancel checks
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   694
        ThreadLocalRandom randomYields = null; // bound if needed
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   695
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   696
        for (;;) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   697
            Object item = s.item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   698
            if (item != e) {                  // matched
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   699
                // assert item != s;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   700
                s.forgetContents();           // avoid garbage
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   701
                return this.<E>cast(item);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   702
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   703
            if ((w.isInterrupted() || (timed && nanos <= 0)) &&
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   704
                    s.casItem(e, s)) {        // cancel
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   705
                unsplice(pred, s);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   706
                return e;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   707
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   708
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   709
            if (spins < 0) {                  // establish spins at/near front
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   710
                if ((spins = spinsFor(pred, s.isData)) > 0)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   711
                    randomYields = ThreadLocalRandom.current();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   712
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   713
            else if (spins > 0) {             // spin
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   714
                --spins;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   715
                if (randomYields.nextInt(CHAINED_SPINS) == 0)
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   716
                    Thread.yield();           // occasionally yield
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   717
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   718
            else if (s.waiter == null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   719
                s.waiter = w;                 // request unpark then recheck
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   720
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   721
            else if (timed) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   722
                long now = System.nanoTime();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   723
                if ((nanos -= now - lastTime) > 0)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   724
                    LockSupport.parkNanos(this, nanos);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   725
                lastTime = now;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   726
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   727
            else {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   728
                LockSupport.park(this);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   729
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   730
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   731
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   732
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   733
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   734
     * Returns spin/yield value for a node with given predecessor and
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   735
     * data mode. See above for explanation.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   736
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   737
    private static int spinsFor(Node pred, boolean haveData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   738
        if (MP && pred != null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   739
            if (pred.isData != haveData)      // phase change
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   740
                return FRONT_SPINS + CHAINED_SPINS;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   741
            if (pred.isMatched())             // probably at front
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   742
                return FRONT_SPINS;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   743
            if (pred.waiter == null)          // pred apparently spinning
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   744
                return CHAINED_SPINS;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   745
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   746
        return 0;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   747
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   748
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   749
    /* -------------- Traversal methods -------------- */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   750
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   751
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   752
     * Returns the successor of p, or the head node if p.next has been
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   753
     * linked to self, which will only be true if traversing with a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   754
     * stale pointer that is now off the list.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   755
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   756
    final Node succ(Node p) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   757
        Node next = p.next;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   758
        return (p == next) ? head : next;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   759
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   760
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   761
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   762
     * Returns the first unmatched node of the given mode, or null if
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   763
     * none.  Used by methods isEmpty, hasWaitingConsumer.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   764
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   765
    private Node firstOfMode(boolean isData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   766
        for (Node p = head; p != null; p = succ(p)) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   767
            if (!p.isMatched())
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   768
                return (p.isData == isData) ? p : null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   769
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   770
        return null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   771
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   772
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   773
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   774
     * Returns the item in the first unmatched node with isData; or
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   775
     * null if none.  Used by peek.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   776
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   777
    private E firstDataItem() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   778
        for (Node p = head; p != null; p = succ(p)) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   779
            Object item = p.item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   780
            if (p.isData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   781
                if (item != null && item != p)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   782
                    return this.<E>cast(item);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   783
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   784
            else if (item == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   785
                return null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   786
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   787
        return null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   788
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   789
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   790
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   791
     * Traverses and counts unmatched nodes of the given mode.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   792
     * Used by methods size and getWaitingConsumerCount.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   793
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   794
    private int countOfMode(boolean data) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   795
        int count = 0;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   796
        for (Node p = head; p != null; ) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   797
            if (!p.isMatched()) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   798
                if (p.isData != data)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   799
                    return 0;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   800
                if (++count == Integer.MAX_VALUE) // saturated
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   801
                    break;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   802
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   803
            Node n = p.next;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   804
            if (n != p)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   805
                p = n;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   806
            else {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   807
                count = 0;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   808
                p = head;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   809
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   810
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   811
        return count;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   812
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   813
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   814
    final class Itr implements Iterator<E> {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   815
        private Node nextNode;   // next node to return item for
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   816
        private E nextItem;      // the corresponding item
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   817
        private Node lastRet;    // last returned node, to support remove
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   818
        private Node lastPred;   // predecessor to unlink lastRet
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   819
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   820
        /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   821
         * Moves to next node after prev, or first node if prev null.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   822
         */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   823
        private void advance(Node prev) {
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   824
            /*
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   825
             * To track and avoid buildup of deleted nodes in the face
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   826
             * of calls to both Queue.remove and Itr.remove, we must
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   827
             * include variants of unsplice and sweep upon each
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   828
             * advance: Upon Itr.remove, we may need to catch up links
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   829
             * from lastPred, and upon other removes, we might need to
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   830
             * skip ahead from stale nodes and unsplice deleted ones
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   831
             * found while advancing.
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   832
             */
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   833
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   834
            Node r, b; // reset lastPred upon possible deletion of lastRet
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   835
            if ((r = lastRet) != null && !r.isMatched())
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   836
                lastPred = r;    // next lastPred is old lastRet
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   837
            else if ((b = lastPred) == null || b.isMatched())
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   838
                lastPred = null; // at start of list
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   839
            else {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   840
                Node s, n;       // help with removal of lastPred.next
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   841
                while ((s = b.next) != null &&
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   842
                       s != b && s.isMatched() &&
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   843
                       (n = s.next) != null && n != s)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   844
                    b.casNext(s, n);
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   845
            }
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   846
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   847
            this.lastRet = prev;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   848
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   849
            for (Node p = prev, s, n;;) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   850
                s = (p == null) ? head : p.next;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   851
                if (s == null)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   852
                    break;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   853
                else if (s == p) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   854
                    p = null;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   855
                    continue;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   856
                }
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   857
                Object item = s.item;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   858
                if (s.isData) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   859
                    if (item != null && item != s) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   860
                        nextItem = LinkedTransferQueue.<E>cast(item);
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   861
                        nextNode = s;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   862
                        return;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   863
                    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   864
                }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   865
                else if (item == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   866
                    break;
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   867
                // assert s.isMatched();
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   868
                if (p == null)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   869
                    p = s;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   870
                else if ((n = s.next) == null)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   871
                    break;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   872
                else if (s == n)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   873
                    p = null;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   874
                else
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   875
                    p.casNext(s, n);
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   876
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   877
            nextNode = null;
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   878
            nextItem = null;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   879
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   880
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   881
        Itr() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   882
            advance(null);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   883
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   884
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   885
        public final boolean hasNext() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   886
            return nextNode != null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   887
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   888
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   889
        public final E next() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   890
            Node p = nextNode;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   891
            if (p == null) throw new NoSuchElementException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   892
            E e = nextItem;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   893
            advance(p);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   894
            return e;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   895
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   896
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   897
        public final void remove() {
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   898
            final Node lastRet = this.lastRet;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   899
            if (lastRet == null)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   900
                throw new IllegalStateException();
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   901
            this.lastRet = null;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   902
            if (lastRet.tryMatchData())
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
   903
                unsplice(lastPred, lastRet);
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   904
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   905
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   906
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   907
    /* -------------- Removal methods -------------- */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   908
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   909
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   910
     * Unsplices (now or later) the given deleted/cancelled node with
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   911
     * the given predecessor.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   912
     *
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   913
     * @param pred a node that was at one time known to be the
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   914
     * predecessor of s, or null or s itself if s is/was at head
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   915
     * @param s the node to be unspliced
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   916
     */
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   917
    final void unsplice(Node pred, Node s) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   918
        s.forgetContents(); // forget unneeded fields
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   919
        /*
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   920
         * See above for rationale. Briefly: if pred still points to
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   921
         * s, try to unlink s.  If s cannot be unlinked, because it is
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   922
         * trailing node or pred might be unlinked, and neither pred
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   923
         * nor s are head or offlist, add to sweepVotes, and if enough
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   924
         * votes have accumulated, sweep.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   925
         */
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   926
        if (pred != null && pred != s && pred.next == s) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   927
            Node n = s.next;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   928
            if (n == null ||
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   929
                (n != s && pred.casNext(s, n) && pred.isMatched())) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   930
                for (;;) {               // check if at, or could be, head
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   931
                    Node h = head;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   932
                    if (h == pred || h == s || h == null)
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   933
                        return;          // at head or list empty
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   934
                    if (!h.isMatched())
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   935
                        break;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   936
                    Node hn = h.next;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   937
                    if (hn == null)
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   938
                        return;          // now empty
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   939
                    if (hn != h && casHead(h, hn))
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   940
                        h.forgetNext();  // advance head
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   941
                }
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   942
                if (pred.next != pred && s.next != s) { // recheck if offlist
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   943
                    for (;;) {           // sweep now if enough votes
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   944
                        int v = sweepVotes;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   945
                        if (v < SWEEP_THRESHOLD) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   946
                            if (casSweepVotes(v, v + 1))
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   947
                                break;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   948
                        }
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   949
                        else if (casSweepVotes(v, 0)) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   950
                            sweep();
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   951
                            break;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   952
                        }
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   953
                    }
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   954
                }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   955
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   956
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   957
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   958
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   959
    /**
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   960
     * Unlinks matched (typically cancelled) nodes encountered in a
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   961
     * traversal from head.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   962
     */
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   963
    private void sweep() {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   964
        for (Node p = head, s, n; p != null && (s = p.next) != null; ) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   965
            if (!s.isMatched())
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   966
                // Unmatched nodes are never self-linked
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   967
                p = s;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   968
            else if ((n = s.next) == null) // trailing node is pinned
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   969
                break;
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   970
            else if (s == n)    // stale
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   971
                // No need to also check for p == s, since that implies s == n
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   972
                p = head;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   973
            else
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
   974
                p.casNext(s, n);
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   975
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   976
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   977
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   978
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   979
     * Main implementation of remove(Object)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   980
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   981
    private boolean findAndRemove(Object e) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   982
        if (e != null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   983
            for (Node pred = null, p = head; p != null; ) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   984
                Object item = p.item;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   985
                if (p.isData) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   986
                    if (item != null && item != p && e.equals(item) &&
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   987
                        p.tryMatchData()) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   988
                        unsplice(pred, p);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   989
                        return true;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   990
                    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   991
                }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   992
                else if (item == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   993
                    break;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   994
                pred = p;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   995
                if ((p = p.next) == pred) { // stale
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   996
                    pred = null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   997
                    p = head;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   998
                }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
   999
            }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1000
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1001
        return false;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1002
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1003
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1004
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1005
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1006
     * Creates an initially empty {@code LinkedTransferQueue}.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1007
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1008
    public LinkedTransferQueue() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1009
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1010
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1011
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1012
     * Creates a {@code LinkedTransferQueue}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1013
     * initially containing the elements of the given collection,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1014
     * added in traversal order of the collection's iterator.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1015
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1016
     * @param c the collection of elements to initially contain
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1017
     * @throws NullPointerException if the specified collection or any
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1018
     *         of its elements are null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1019
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1020
    public LinkedTransferQueue(Collection<? extends E> c) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1021
        this();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1022
        addAll(c);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1023
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1024
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1025
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1026
     * Inserts the specified element at the tail of this queue.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1027
     * As the queue is unbounded, this method will never block.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1028
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1029
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1030
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1031
    public void put(E e) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1032
        xfer(e, true, ASYNC, 0);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1033
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1034
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1035
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1036
     * Inserts the specified element at the tail of this queue.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1037
     * As the queue is unbounded, this method will never block or
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1038
     * return {@code false}.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1039
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1040
     * @return {@code true} (as specified by
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1041
     *  {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1042
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1043
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1044
    public boolean offer(E e, long timeout, TimeUnit unit) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1045
        xfer(e, true, ASYNC, 0);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1046
        return true;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1047
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1048
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1049
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1050
     * Inserts the specified element at the tail of this queue.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1051
     * As the queue is unbounded, this method will never return {@code false}.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1052
     *
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1053
     * @return {@code true} (as specified by {@link Queue#offer})
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1054
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1055
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1056
    public boolean offer(E e) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1057
        xfer(e, true, ASYNC, 0);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1058
        return true;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1059
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1060
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1061
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1062
     * Inserts the specified element at the tail of this queue.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1063
     * As the queue is unbounded, this method will never throw
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1064
     * {@link IllegalStateException} or return {@code false}.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1065
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1066
     * @return {@code true} (as specified by {@link Collection#add})
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1067
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1068
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1069
    public boolean add(E e) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1070
        xfer(e, true, ASYNC, 0);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1071
        return true;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1072
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1073
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1074
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1075
     * Transfers the element to a waiting consumer immediately, if possible.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1076
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1077
     * <p>More precisely, transfers the specified element immediately
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1078
     * if there exists a consumer already waiting to receive it (in
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1079
     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1080
     * otherwise returning {@code false} without enqueuing the element.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1081
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1082
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1083
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1084
    public boolean tryTransfer(E e) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1085
        return xfer(e, true, NOW, 0) == null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1086
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1087
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1088
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1089
     * Transfers the element to a consumer, waiting if necessary to do so.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1090
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1091
     * <p>More precisely, transfers the specified element immediately
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1092
     * if there exists a consumer already waiting to receive it (in
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1093
     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1094
     * else inserts the specified element at the tail of this queue
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1095
     * and waits until the element is received by a consumer.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1096
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1097
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1098
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1099
    public void transfer(E e) throws InterruptedException {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1100
        if (xfer(e, true, SYNC, 0) != null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1101
            Thread.interrupted(); // failure possible only due to interrupt
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1102
            throw new InterruptedException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1103
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1104
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1105
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1106
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1107
     * Transfers the element to a consumer if it is possible to do so
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1108
     * before the timeout elapses.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1109
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1110
     * <p>More precisely, transfers the specified element immediately
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1111
     * if there exists a consumer already waiting to receive it (in
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1112
     * {@link #take} or timed {@link #poll(long,TimeUnit) poll}),
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1113
     * else inserts the specified element at the tail of this queue
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1114
     * and waits until the element is received by a consumer,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1115
     * returning {@code false} if the specified wait time elapses
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1116
     * before the element can be transferred.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1117
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1118
     * @throws NullPointerException if the specified element is null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1119
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1120
    public boolean tryTransfer(E e, long timeout, TimeUnit unit)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1121
        throws InterruptedException {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1122
        if (xfer(e, true, TIMED, unit.toNanos(timeout)) == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1123
            return true;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1124
        if (!Thread.interrupted())
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1125
            return false;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1126
        throw new InterruptedException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1127
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1128
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1129
    public E take() throws InterruptedException {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1130
        E e = xfer(null, false, SYNC, 0);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1131
        if (e != null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1132
            return e;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1133
        Thread.interrupted();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1134
        throw new InterruptedException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1135
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1136
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1137
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1138
        E e = xfer(null, false, TIMED, unit.toNanos(timeout));
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1139
        if (e != null || !Thread.interrupted())
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1140
            return e;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1141
        throw new InterruptedException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1142
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1143
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1144
    public E poll() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1145
        return xfer(null, false, NOW, 0);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1146
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1147
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1148
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1149
     * @throws NullPointerException     {@inheritDoc}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1150
     * @throws IllegalArgumentException {@inheritDoc}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1151
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1152
    public int drainTo(Collection<? super E> c) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1153
        if (c == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1154
            throw new NullPointerException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1155
        if (c == this)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1156
            throw new IllegalArgumentException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1157
        int n = 0;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1158
        E e;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1159
        while ( (e = poll()) != null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1160
            c.add(e);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1161
            ++n;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1162
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1163
        return n;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1164
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1165
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1166
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1167
     * @throws NullPointerException     {@inheritDoc}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1168
     * @throws IllegalArgumentException {@inheritDoc}
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1169
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1170
    public int drainTo(Collection<? super E> c, int maxElements) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1171
        if (c == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1172
            throw new NullPointerException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1173
        if (c == this)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1174
            throw new IllegalArgumentException();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1175
        int n = 0;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1176
        E e;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1177
        while (n < maxElements && (e = poll()) != null) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1178
            c.add(e);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1179
            ++n;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1180
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1181
        return n;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1182
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1183
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1184
    /**
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1185
     * Returns an iterator over the elements in this queue in proper sequence.
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1186
     * The elements will be returned in order from first (head) to last (tail).
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1187
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1188
     * <p>The returned iterator is a "weakly consistent" iterator that
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1189
     * will never throw {@link java.util.ConcurrentModificationException
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1190
     * ConcurrentModificationException}, and guarantees to traverse
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1191
     * elements as they existed upon construction of the iterator, and
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1192
     * may (but is not guaranteed to) reflect any modifications
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1193
     * subsequent to construction.
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1194
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1195
     * @return an iterator over the elements in this queue in proper sequence
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1196
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1197
    public Iterator<E> iterator() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1198
        return new Itr();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1199
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1200
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1201
    public E peek() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1202
        return firstDataItem();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1203
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1204
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1205
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1206
     * Returns {@code true} if this queue contains no elements.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1207
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1208
     * @return {@code true} if this queue contains no elements
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1209
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1210
    public boolean isEmpty() {
6543
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
  1211
        for (Node p = head; p != null; p = succ(p)) {
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
  1212
            if (!p.isMatched())
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
  1213
                return !p.isData;
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
  1214
        }
c06e5f2c6bb1 6978087: jsr166y Updates
dl
parents: 5506
diff changeset
  1215
        return true;
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1216
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1217
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1218
    public boolean hasWaitingConsumer() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1219
        return firstOfMode(false) != null;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1220
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1221
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1222
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1223
     * Returns the number of elements in this queue.  If this queue
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1224
     * contains more than {@code Integer.MAX_VALUE} elements, returns
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1225
     * {@code Integer.MAX_VALUE}.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1226
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1227
     * <p>Beware that, unlike in most collections, this method is
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1228
     * <em>NOT</em> a constant-time operation. Because of the
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1229
     * asynchronous nature of these queues, determining the current
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1230
     * number of elements requires an O(n) traversal.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1231
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1232
     * @return the number of elements in this queue
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1233
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1234
    public int size() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1235
        return countOfMode(true);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1236
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1237
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1238
    public int getWaitingConsumerCount() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1239
        return countOfMode(false);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1240
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1241
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1242
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1243
     * Removes a single instance of the specified element from this queue,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1244
     * if it is present.  More formally, removes an element {@code e} such
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1245
     * that {@code o.equals(e)}, if this queue contains one or more such
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1246
     * elements.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1247
     * Returns {@code true} if this queue contained the specified element
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1248
     * (or equivalently, if this queue changed as a result of the call).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1249
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1250
     * @param o element to be removed from this queue, if present
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1251
     * @return {@code true} if this queue changed as a result of the call
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1252
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1253
    public boolean remove(Object o) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1254
        return findAndRemove(o);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1255
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1256
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1257
    /**
7976
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1258
     * Returns {@code true} if this queue contains the specified element.
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1259
     * More formally, returns {@code true} if and only if this queue contains
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1260
     * at least one element {@code e} such that {@code o.equals(e)}.
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1261
     *
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1262
     * @param o object to be checked for containment in this queue
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1263
     * @return {@code true} if this queue contains the specified element
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1264
     */
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1265
    public boolean contains(Object o) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1266
        if (o == null) return false;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1267
        for (Node p = head; p != null; p = succ(p)) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1268
            Object item = p.item;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1269
            if (p.isData) {
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1270
                if (item != null && item != p && o.equals(item))
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1271
                    return true;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1272
            }
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1273
            else if (item == null)
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1274
                break;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1275
        }
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1276
        return false;
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1277
    }
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1278
f273c0d04215 7005424: Resync java.util.concurrent classes with Dougs CVS - Jan 2011
dl
parents: 6543
diff changeset
  1279
    /**
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1280
     * Always returns {@code Integer.MAX_VALUE} because a
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1281
     * {@code LinkedTransferQueue} is not capacity constrained.
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1282
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1283
     * @return {@code Integer.MAX_VALUE} (as specified by
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1284
     *         {@link BlockingQueue#remainingCapacity()})
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1285
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1286
    public int remainingCapacity() {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1287
        return Integer.MAX_VALUE;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1288
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1289
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1290
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1291
     * Saves the state to a stream (that is, serializes it).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1292
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1293
     * @serialData All of the elements (each an {@code E}) in
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1294
     * the proper order, followed by a null
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1295
     * @param s the stream
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1296
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1297
    private void writeObject(java.io.ObjectOutputStream s)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1298
        throws java.io.IOException {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1299
        s.defaultWriteObject();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1300
        for (E e : this)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1301
            s.writeObject(e);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1302
        // Use trailing null as sentinel
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1303
        s.writeObject(null);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1304
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1305
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1306
    /**
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1307
     * Reconstitutes the Queue instance from a stream (that is,
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1308
     * deserializes it).
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1309
     *
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1310
     * @param s the stream
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1311
     */
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1312
    private void readObject(java.io.ObjectInputStream s)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1313
        throws java.io.IOException, ClassNotFoundException {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1314
        s.defaultReadObject();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1315
        for (;;) {
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1316
            @SuppressWarnings("unchecked") E item = (E) s.readObject();
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1317
            if (item == null)
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1318
                break;
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1319
            else
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1320
                offer(item);
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1321
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1322
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1323
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1324
    // Unsafe mechanics
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1325
8544
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1326
    private static final sun.misc.Unsafe UNSAFE;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1327
    private static final long headOffset;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1328
    private static final long tailOffset;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1329
    private static final long sweepVotesOffset;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1330
    static {
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1331
        try {
8544
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1332
            UNSAFE = sun.misc.Unsafe.getUnsafe();
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1333
            Class k = LinkedTransferQueue.class;
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1334
            headOffset = UNSAFE.objectFieldOffset
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1335
                (k.getDeclaredField("head"));
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1336
            tailOffset = UNSAFE.objectFieldOffset
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1337
                (k.getDeclaredField("tail"));
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1338
            sweepVotesOffset = UNSAFE.objectFieldOffset
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1339
                (k.getDeclaredField("sweepVotes"));
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1340
        } catch (Exception e) {
225896f7b33c 7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
dl
parents: 7976
diff changeset
  1341
            throw new Error(e);
4110
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1342
        }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1343
    }
ac033ba6ede4 6865582: jsr166y - jsr166 maintenance update
dl
parents:
diff changeset
  1344
}