rt/emul/compact/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 19 Mar 2016 10:46:31 +0100
branchjdk7-b147
changeset 1890 212417b74b72
child 1895 bfaf3300b7ba
permissions -rw-r--r--
Bringing in all concurrent package from JDK7-b147
jaroslav@1890
     1
/*
jaroslav@1890
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jaroslav@1890
     3
 *
jaroslav@1890
     4
 * This code is free software; you can redistribute it and/or modify it
jaroslav@1890
     5
 * under the terms of the GNU General Public License version 2 only, as
jaroslav@1890
     6
 * published by the Free Software Foundation.  Oracle designates this
jaroslav@1890
     7
 * particular file as subject to the "Classpath" exception as provided
jaroslav@1890
     8
 * by Oracle in the LICENSE file that accompanied this code.
jaroslav@1890
     9
 *
jaroslav@1890
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
jaroslav@1890
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jaroslav@1890
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
jaroslav@1890
    13
 * version 2 for more details (a copy is included in the LICENSE file that
jaroslav@1890
    14
 * accompanied this code).
jaroslav@1890
    15
 *
jaroslav@1890
    16
 * You should have received a copy of the GNU General Public License version
jaroslav@1890
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
jaroslav@1890
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jaroslav@1890
    19
 *
jaroslav@1890
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jaroslav@1890
    21
 * or visit www.oracle.com if you need additional information or have any
jaroslav@1890
    22
 * questions.
jaroslav@1890
    23
 */
jaroslav@1890
    24
jaroslav@1890
    25
/*
jaroslav@1890
    26
 * This file is available under and governed by the GNU General Public
jaroslav@1890
    27
 * License version 2 only, as published by the Free Software Foundation.
jaroslav@1890
    28
 * However, the following notice accompanied the original version of this
jaroslav@1890
    29
 * file:
jaroslav@1890
    30
 *
jaroslav@1890
    31
 * Written by Doug Lea with assistance from members of JCP JSR-166
jaroslav@1890
    32
 * Expert Group and released to the public domain, as explained at
jaroslav@1890
    33
 * http://creativecommons.org/publicdomain/zero/1.0/
jaroslav@1890
    34
 */
jaroslav@1890
    35
jaroslav@1890
    36
package java.util.concurrent;
jaroslav@1890
    37
jaroslav@1890
    38
import java.util.concurrent.locks.*;
jaroslav@1890
    39
import java.util.*;
jaroslav@1890
    40
jaroslav@1890
    41
/**
jaroslav@1890
    42
 * An unbounded {@linkplain BlockingQueue blocking queue} that uses
jaroslav@1890
    43
 * the same ordering rules as class {@link PriorityQueue} and supplies
jaroslav@1890
    44
 * blocking retrieval operations.  While this queue is logically
jaroslav@1890
    45
 * unbounded, attempted additions may fail due to resource exhaustion
jaroslav@1890
    46
 * (causing {@code OutOfMemoryError}). This class does not permit
jaroslav@1890
    47
 * {@code null} elements.  A priority queue relying on {@linkplain
jaroslav@1890
    48
 * Comparable natural ordering} also does not permit insertion of
jaroslav@1890
    49
 * non-comparable objects (doing so results in
jaroslav@1890
    50
 * {@code ClassCastException}).
jaroslav@1890
    51
 *
jaroslav@1890
    52
 * <p>This class and its iterator implement all of the
jaroslav@1890
    53
 * <em>optional</em> methods of the {@link Collection} and {@link
jaroslav@1890
    54
 * Iterator} interfaces.  The Iterator provided in method {@link
jaroslav@1890
    55
 * #iterator()} is <em>not</em> guaranteed to traverse the elements of
jaroslav@1890
    56
 * the PriorityBlockingQueue in any particular order. If you need
jaroslav@1890
    57
 * ordered traversal, consider using
jaroslav@1890
    58
 * {@code Arrays.sort(pq.toArray())}.  Also, method {@code drainTo}
jaroslav@1890
    59
 * can be used to <em>remove</em> some or all elements in priority
jaroslav@1890
    60
 * order and place them in another collection.
jaroslav@1890
    61
 *
jaroslav@1890
    62
 * <p>Operations on this class make no guarantees about the ordering
jaroslav@1890
    63
 * of elements with equal priority. If you need to enforce an
jaroslav@1890
    64
 * ordering, you can define custom classes or comparators that use a
jaroslav@1890
    65
 * secondary key to break ties in primary priority values.  For
jaroslav@1890
    66
 * example, here is a class that applies first-in-first-out
jaroslav@1890
    67
 * tie-breaking to comparable elements. To use it, you would insert a
jaroslav@1890
    68
 * {@code new FIFOEntry(anEntry)} instead of a plain entry object.
jaroslav@1890
    69
 *
jaroslav@1890
    70
 *  <pre> {@code
jaroslav@1890
    71
 * class FIFOEntry<E extends Comparable<? super E>>
jaroslav@1890
    72
 *     implements Comparable<FIFOEntry<E>> {
jaroslav@1890
    73
 *   static final AtomicLong seq = new AtomicLong(0);
jaroslav@1890
    74
 *   final long seqNum;
jaroslav@1890
    75
 *   final E entry;
jaroslav@1890
    76
 *   public FIFOEntry(E entry) {
jaroslav@1890
    77
 *     seqNum = seq.getAndIncrement();
jaroslav@1890
    78
 *     this.entry = entry;
jaroslav@1890
    79
 *   }
jaroslav@1890
    80
 *   public E getEntry() { return entry; }
jaroslav@1890
    81
 *   public int compareTo(FIFOEntry<E> other) {
jaroslav@1890
    82
 *     int res = entry.compareTo(other.entry);
jaroslav@1890
    83
 *     if (res == 0 && other.entry != this.entry)
jaroslav@1890
    84
 *       res = (seqNum < other.seqNum ? -1 : 1);
jaroslav@1890
    85
 *     return res;
jaroslav@1890
    86
 *   }
jaroslav@1890
    87
 * }}</pre>
jaroslav@1890
    88
 *
jaroslav@1890
    89
 * <p>This class is a member of the
jaroslav@1890
    90
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
jaroslav@1890
    91
 * Java Collections Framework</a>.
jaroslav@1890
    92
 *
jaroslav@1890
    93
 * @since 1.5
jaroslav@1890
    94
 * @author Doug Lea
jaroslav@1890
    95
 * @param <E> the type of elements held in this collection
jaroslav@1890
    96
 */
jaroslav@1890
    97
public class PriorityBlockingQueue<E> extends AbstractQueue<E>
jaroslav@1890
    98
    implements BlockingQueue<E>, java.io.Serializable {
jaroslav@1890
    99
    private static final long serialVersionUID = 5595510919245408276L;
jaroslav@1890
   100
jaroslav@1890
   101
    /*
jaroslav@1890
   102
     * The implementation uses an array-based binary heap, with public
jaroslav@1890
   103
     * operations protected with a single lock. However, allocation
jaroslav@1890
   104
     * during resizing uses a simple spinlock (used only while not
jaroslav@1890
   105
     * holding main lock) in order to allow takes to operate
jaroslav@1890
   106
     * concurrently with allocation.  This avoids repeated
jaroslav@1890
   107
     * postponement of waiting consumers and consequent element
jaroslav@1890
   108
     * build-up. The need to back away from lock during allocation
jaroslav@1890
   109
     * makes it impossible to simply wrap delegated
jaroslav@1890
   110
     * java.util.PriorityQueue operations within a lock, as was done
jaroslav@1890
   111
     * in a previous version of this class. To maintain
jaroslav@1890
   112
     * interoperability, a plain PriorityQueue is still used during
jaroslav@1890
   113
     * serialization, which maintains compatibility at the espense of
jaroslav@1890
   114
     * transiently doubling overhead.
jaroslav@1890
   115
     */
jaroslav@1890
   116
jaroslav@1890
   117
    /**
jaroslav@1890
   118
     * Default array capacity.
jaroslav@1890
   119
     */
jaroslav@1890
   120
    private static final int DEFAULT_INITIAL_CAPACITY = 11;
jaroslav@1890
   121
jaroslav@1890
   122
    /**
jaroslav@1890
   123
     * The maximum size of array to allocate.
jaroslav@1890
   124
     * Some VMs reserve some header words in an array.
jaroslav@1890
   125
     * Attempts to allocate larger arrays may result in
jaroslav@1890
   126
     * OutOfMemoryError: Requested array size exceeds VM limit
jaroslav@1890
   127
     */
jaroslav@1890
   128
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
jaroslav@1890
   129
jaroslav@1890
   130
    /**
jaroslav@1890
   131
     * Priority queue represented as a balanced binary heap: the two
jaroslav@1890
   132
     * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].  The
jaroslav@1890
   133
     * priority queue is ordered by comparator, or by the elements'
jaroslav@1890
   134
     * natural ordering, if comparator is null: For each node n in the
jaroslav@1890
   135
     * heap and each descendant d of n, n <= d.  The element with the
jaroslav@1890
   136
     * lowest value is in queue[0], assuming the queue is nonempty.
jaroslav@1890
   137
     */
jaroslav@1890
   138
    private transient Object[] queue;
jaroslav@1890
   139
jaroslav@1890
   140
    /**
jaroslav@1890
   141
     * The number of elements in the priority queue.
jaroslav@1890
   142
     */
jaroslav@1890
   143
    private transient int size;
jaroslav@1890
   144
jaroslav@1890
   145
    /**
jaroslav@1890
   146
     * The comparator, or null if priority queue uses elements'
jaroslav@1890
   147
     * natural ordering.
jaroslav@1890
   148
     */
jaroslav@1890
   149
    private transient Comparator<? super E> comparator;
jaroslav@1890
   150
jaroslav@1890
   151
    /**
jaroslav@1890
   152
     * Lock used for all public operations
jaroslav@1890
   153
     */
jaroslav@1890
   154
    private final ReentrantLock lock;
jaroslav@1890
   155
jaroslav@1890
   156
    /**
jaroslav@1890
   157
     * Condition for blocking when empty
jaroslav@1890
   158
     */
jaroslav@1890
   159
    private final Condition notEmpty;
jaroslav@1890
   160
jaroslav@1890
   161
    /**
jaroslav@1890
   162
     * Spinlock for allocation, acquired via CAS.
jaroslav@1890
   163
     */
jaroslav@1890
   164
    private transient volatile int allocationSpinLock;
jaroslav@1890
   165
jaroslav@1890
   166
    /**
jaroslav@1890
   167
     * A plain PriorityQueue used only for serialization,
jaroslav@1890
   168
     * to maintain compatibility with previous versions
jaroslav@1890
   169
     * of this class. Non-null only during serialization/deserialization.
jaroslav@1890
   170
     */
jaroslav@1890
   171
    private PriorityQueue q;
jaroslav@1890
   172
jaroslav@1890
   173
    /**
jaroslav@1890
   174
     * Creates a {@code PriorityBlockingQueue} with the default
jaroslav@1890
   175
     * initial capacity (11) that orders its elements according to
jaroslav@1890
   176
     * their {@linkplain Comparable natural ordering}.
jaroslav@1890
   177
     */
jaroslav@1890
   178
    public PriorityBlockingQueue() {
jaroslav@1890
   179
        this(DEFAULT_INITIAL_CAPACITY, null);
jaroslav@1890
   180
    }
jaroslav@1890
   181
jaroslav@1890
   182
    /**
jaroslav@1890
   183
     * Creates a {@code PriorityBlockingQueue} with the specified
jaroslav@1890
   184
     * initial capacity that orders its elements according to their
jaroslav@1890
   185
     * {@linkplain Comparable natural ordering}.
jaroslav@1890
   186
     *
jaroslav@1890
   187
     * @param initialCapacity the initial capacity for this priority queue
jaroslav@1890
   188
     * @throws IllegalArgumentException if {@code initialCapacity} is less
jaroslav@1890
   189
     *         than 1
jaroslav@1890
   190
     */
jaroslav@1890
   191
    public PriorityBlockingQueue(int initialCapacity) {
jaroslav@1890
   192
        this(initialCapacity, null);
jaroslav@1890
   193
    }
jaroslav@1890
   194
jaroslav@1890
   195
    /**
jaroslav@1890
   196
     * Creates a {@code PriorityBlockingQueue} with the specified initial
jaroslav@1890
   197
     * capacity that orders its elements according to the specified
jaroslav@1890
   198
     * comparator.
jaroslav@1890
   199
     *
jaroslav@1890
   200
     * @param initialCapacity the initial capacity for this priority queue
jaroslav@1890
   201
     * @param  comparator the comparator that will be used to order this
jaroslav@1890
   202
     *         priority queue.  If {@code null}, the {@linkplain Comparable
jaroslav@1890
   203
     *         natural ordering} of the elements will be used.
jaroslav@1890
   204
     * @throws IllegalArgumentException if {@code initialCapacity} is less
jaroslav@1890
   205
     *         than 1
jaroslav@1890
   206
     */
jaroslav@1890
   207
    public PriorityBlockingQueue(int initialCapacity,
jaroslav@1890
   208
                                 Comparator<? super E> comparator) {
jaroslav@1890
   209
        if (initialCapacity < 1)
jaroslav@1890
   210
            throw new IllegalArgumentException();
jaroslav@1890
   211
        this.lock = new ReentrantLock();
jaroslav@1890
   212
        this.notEmpty = lock.newCondition();
jaroslav@1890
   213
        this.comparator = comparator;
jaroslav@1890
   214
        this.queue = new Object[initialCapacity];
jaroslav@1890
   215
    }
jaroslav@1890
   216
jaroslav@1890
   217
    /**
jaroslav@1890
   218
     * Creates a {@code PriorityBlockingQueue} containing the elements
jaroslav@1890
   219
     * in the specified collection.  If the specified collection is a
jaroslav@1890
   220
     * {@link SortedSet} or a {@link PriorityQueue},  this
jaroslav@1890
   221
     * priority queue will be ordered according to the same ordering.
jaroslav@1890
   222
     * Otherwise, this priority queue will be ordered according to the
jaroslav@1890
   223
     * {@linkplain Comparable natural ordering} of its elements.
jaroslav@1890
   224
     *
jaroslav@1890
   225
     * @param  c the collection whose elements are to be placed
jaroslav@1890
   226
     *         into this priority queue
jaroslav@1890
   227
     * @throws ClassCastException if elements of the specified collection
jaroslav@1890
   228
     *         cannot be compared to one another according to the priority
jaroslav@1890
   229
     *         queue's ordering
jaroslav@1890
   230
     * @throws NullPointerException if the specified collection or any
jaroslav@1890
   231
     *         of its elements are null
jaroslav@1890
   232
     */
jaroslav@1890
   233
    public PriorityBlockingQueue(Collection<? extends E> c) {
jaroslav@1890
   234
        this.lock = new ReentrantLock();
jaroslav@1890
   235
        this.notEmpty = lock.newCondition();
jaroslav@1890
   236
        boolean heapify = true; // true if not known to be in heap order
jaroslav@1890
   237
        boolean screen = true;  // true if must screen for nulls
jaroslav@1890
   238
        if (c instanceof SortedSet<?>) {
jaroslav@1890
   239
            SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
jaroslav@1890
   240
            this.comparator = (Comparator<? super E>) ss.comparator();
jaroslav@1890
   241
            heapify = false;
jaroslav@1890
   242
        }
jaroslav@1890
   243
        else if (c instanceof PriorityBlockingQueue<?>) {
jaroslav@1890
   244
            PriorityBlockingQueue<? extends E> pq =
jaroslav@1890
   245
                (PriorityBlockingQueue<? extends E>) c;
jaroslav@1890
   246
            this.comparator = (Comparator<? super E>) pq.comparator();
jaroslav@1890
   247
            screen = false;
jaroslav@1890
   248
            if (pq.getClass() == PriorityBlockingQueue.class) // exact match
jaroslav@1890
   249
                heapify = false;
jaroslav@1890
   250
        }
jaroslav@1890
   251
        Object[] a = c.toArray();
jaroslav@1890
   252
        int n = a.length;
jaroslav@1890
   253
        // If c.toArray incorrectly doesn't return Object[], copy it.
jaroslav@1890
   254
        if (a.getClass() != Object[].class)
jaroslav@1890
   255
            a = Arrays.copyOf(a, n, Object[].class);
jaroslav@1890
   256
        if (screen && (n == 1 || this.comparator != null)) {
jaroslav@1890
   257
            for (int i = 0; i < n; ++i)
jaroslav@1890
   258
                if (a[i] == null)
jaroslav@1890
   259
                    throw new NullPointerException();
jaroslav@1890
   260
        }
jaroslav@1890
   261
        this.queue = a;
jaroslav@1890
   262
        this.size = n;
jaroslav@1890
   263
        if (heapify)
jaroslav@1890
   264
            heapify();
jaroslav@1890
   265
    }
jaroslav@1890
   266
jaroslav@1890
   267
    /**
jaroslav@1890
   268
     * Tries to grow array to accommodate at least one more element
jaroslav@1890
   269
     * (but normally expand by about 50%), giving up (allowing retry)
jaroslav@1890
   270
     * on contention (which we expect to be rare). Call only while
jaroslav@1890
   271
     * holding lock.
jaroslav@1890
   272
     *
jaroslav@1890
   273
     * @param array the heap array
jaroslav@1890
   274
     * @param oldCap the length of the array
jaroslav@1890
   275
     */
jaroslav@1890
   276
    private void tryGrow(Object[] array, int oldCap) {
jaroslav@1890
   277
        lock.unlock(); // must release and then re-acquire main lock
jaroslav@1890
   278
        Object[] newArray = null;
jaroslav@1890
   279
        if (allocationSpinLock == 0 &&
jaroslav@1890
   280
            UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset,
jaroslav@1890
   281
                                     0, 1)) {
jaroslav@1890
   282
            try {
jaroslav@1890
   283
                int newCap = oldCap + ((oldCap < 64) ?
jaroslav@1890
   284
                                       (oldCap + 2) : // grow faster if small
jaroslav@1890
   285
                                       (oldCap >> 1));
jaroslav@1890
   286
                if (newCap - MAX_ARRAY_SIZE > 0) {    // possible overflow
jaroslav@1890
   287
                    int minCap = oldCap + 1;
jaroslav@1890
   288
                    if (minCap < 0 || minCap > MAX_ARRAY_SIZE)
jaroslav@1890
   289
                        throw new OutOfMemoryError();
jaroslav@1890
   290
                    newCap = MAX_ARRAY_SIZE;
jaroslav@1890
   291
                }
jaroslav@1890
   292
                if (newCap > oldCap && queue == array)
jaroslav@1890
   293
                    newArray = new Object[newCap];
jaroslav@1890
   294
            } finally {
jaroslav@1890
   295
                allocationSpinLock = 0;
jaroslav@1890
   296
            }
jaroslav@1890
   297
        }
jaroslav@1890
   298
        if (newArray == null) // back off if another thread is allocating
jaroslav@1890
   299
            Thread.yield();
jaroslav@1890
   300
        lock.lock();
jaroslav@1890
   301
        if (newArray != null && queue == array) {
jaroslav@1890
   302
            queue = newArray;
jaroslav@1890
   303
            System.arraycopy(array, 0, newArray, 0, oldCap);
jaroslav@1890
   304
        }
jaroslav@1890
   305
    }
jaroslav@1890
   306
jaroslav@1890
   307
    /**
jaroslav@1890
   308
     * Mechanics for poll().  Call only while holding lock.
jaroslav@1890
   309
     */
jaroslav@1890
   310
    private E extract() {
jaroslav@1890
   311
        E result;
jaroslav@1890
   312
        int n = size - 1;
jaroslav@1890
   313
        if (n < 0)
jaroslav@1890
   314
            result = null;
jaroslav@1890
   315
        else {
jaroslav@1890
   316
            Object[] array = queue;
jaroslav@1890
   317
            result = (E) array[0];
jaroslav@1890
   318
            E x = (E) array[n];
jaroslav@1890
   319
            array[n] = null;
jaroslav@1890
   320
            Comparator<? super E> cmp = comparator;
jaroslav@1890
   321
            if (cmp == null)
jaroslav@1890
   322
                siftDownComparable(0, x, array, n);
jaroslav@1890
   323
            else
jaroslav@1890
   324
                siftDownUsingComparator(0, x, array, n, cmp);
jaroslav@1890
   325
            size = n;
jaroslav@1890
   326
        }
jaroslav@1890
   327
        return result;
jaroslav@1890
   328
    }
jaroslav@1890
   329
jaroslav@1890
   330
    /**
jaroslav@1890
   331
     * Inserts item x at position k, maintaining heap invariant by
jaroslav@1890
   332
     * promoting x up the tree until it is greater than or equal to
jaroslav@1890
   333
     * its parent, or is the root.
jaroslav@1890
   334
     *
jaroslav@1890
   335
     * To simplify and speed up coercions and comparisons. the
jaroslav@1890
   336
     * Comparable and Comparator versions are separated into different
jaroslav@1890
   337
     * methods that are otherwise identical. (Similarly for siftDown.)
jaroslav@1890
   338
     * These methods are static, with heap state as arguments, to
jaroslav@1890
   339
     * simplify use in light of possible comparator exceptions.
jaroslav@1890
   340
     *
jaroslav@1890
   341
     * @param k the position to fill
jaroslav@1890
   342
     * @param x the item to insert
jaroslav@1890
   343
     * @param array the heap array
jaroslav@1890
   344
     * @param n heap size
jaroslav@1890
   345
     */
jaroslav@1890
   346
    private static <T> void siftUpComparable(int k, T x, Object[] array) {
jaroslav@1890
   347
        Comparable<? super T> key = (Comparable<? super T>) x;
jaroslav@1890
   348
        while (k > 0) {
jaroslav@1890
   349
            int parent = (k - 1) >>> 1;
jaroslav@1890
   350
            Object e = array[parent];
jaroslav@1890
   351
            if (key.compareTo((T) e) >= 0)
jaroslav@1890
   352
                break;
jaroslav@1890
   353
            array[k] = e;
jaroslav@1890
   354
            k = parent;
jaroslav@1890
   355
        }
jaroslav@1890
   356
        array[k] = key;
jaroslav@1890
   357
    }
jaroslav@1890
   358
jaroslav@1890
   359
    private static <T> void siftUpUsingComparator(int k, T x, Object[] array,
jaroslav@1890
   360
                                       Comparator<? super T> cmp) {
jaroslav@1890
   361
        while (k > 0) {
jaroslav@1890
   362
            int parent = (k - 1) >>> 1;
jaroslav@1890
   363
            Object e = array[parent];
jaroslav@1890
   364
            if (cmp.compare(x, (T) e) >= 0)
jaroslav@1890
   365
                break;
jaroslav@1890
   366
            array[k] = e;
jaroslav@1890
   367
            k = parent;
jaroslav@1890
   368
        }
jaroslav@1890
   369
        array[k] = x;
jaroslav@1890
   370
    }
jaroslav@1890
   371
jaroslav@1890
   372
    /**
jaroslav@1890
   373
     * Inserts item x at position k, maintaining heap invariant by
jaroslav@1890
   374
     * demoting x down the tree repeatedly until it is less than or
jaroslav@1890
   375
     * equal to its children or is a leaf.
jaroslav@1890
   376
     *
jaroslav@1890
   377
     * @param k the position to fill
jaroslav@1890
   378
     * @param x the item to insert
jaroslav@1890
   379
     * @param array the heap array
jaroslav@1890
   380
     * @param n heap size
jaroslav@1890
   381
     */
jaroslav@1890
   382
    private static <T> void siftDownComparable(int k, T x, Object[] array,
jaroslav@1890
   383
                                               int n) {
jaroslav@1890
   384
        Comparable<? super T> key = (Comparable<? super T>)x;
jaroslav@1890
   385
        int half = n >>> 1;           // loop while a non-leaf
jaroslav@1890
   386
        while (k < half) {
jaroslav@1890
   387
            int child = (k << 1) + 1; // assume left child is least
jaroslav@1890
   388
            Object c = array[child];
jaroslav@1890
   389
            int right = child + 1;
jaroslav@1890
   390
            if (right < n &&
jaroslav@1890
   391
                ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
jaroslav@1890
   392
                c = array[child = right];
jaroslav@1890
   393
            if (key.compareTo((T) c) <= 0)
jaroslav@1890
   394
                break;
jaroslav@1890
   395
            array[k] = c;
jaroslav@1890
   396
            k = child;
jaroslav@1890
   397
        }
jaroslav@1890
   398
        array[k] = key;
jaroslav@1890
   399
    }
jaroslav@1890
   400
jaroslav@1890
   401
    private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
jaroslav@1890
   402
                                                    int n,
jaroslav@1890
   403
                                                    Comparator<? super T> cmp) {
jaroslav@1890
   404
        int half = n >>> 1;
jaroslav@1890
   405
        while (k < half) {
jaroslav@1890
   406
            int child = (k << 1) + 1;
jaroslav@1890
   407
            Object c = array[child];
jaroslav@1890
   408
            int right = child + 1;
jaroslav@1890
   409
            if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
jaroslav@1890
   410
                c = array[child = right];
jaroslav@1890
   411
            if (cmp.compare(x, (T) c) <= 0)
jaroslav@1890
   412
                break;
jaroslav@1890
   413
            array[k] = c;
jaroslav@1890
   414
            k = child;
jaroslav@1890
   415
        }
jaroslav@1890
   416
        array[k] = x;
jaroslav@1890
   417
    }
jaroslav@1890
   418
jaroslav@1890
   419
    /**
jaroslav@1890
   420
     * Establishes the heap invariant (described above) in the entire tree,
jaroslav@1890
   421
     * assuming nothing about the order of the elements prior to the call.
jaroslav@1890
   422
     */
jaroslav@1890
   423
    private void heapify() {
jaroslav@1890
   424
        Object[] array = queue;
jaroslav@1890
   425
        int n = size;
jaroslav@1890
   426
        int half = (n >>> 1) - 1;
jaroslav@1890
   427
        Comparator<? super E> cmp = comparator;
jaroslav@1890
   428
        if (cmp == null) {
jaroslav@1890
   429
            for (int i = half; i >= 0; i--)
jaroslav@1890
   430
                siftDownComparable(i, (E) array[i], array, n);
jaroslav@1890
   431
        }
jaroslav@1890
   432
        else {
jaroslav@1890
   433
            for (int i = half; i >= 0; i--)
jaroslav@1890
   434
                siftDownUsingComparator(i, (E) array[i], array, n, cmp);
jaroslav@1890
   435
        }
jaroslav@1890
   436
    }
jaroslav@1890
   437
jaroslav@1890
   438
    /**
jaroslav@1890
   439
     * Inserts the specified element into this priority queue.
jaroslav@1890
   440
     *
jaroslav@1890
   441
     * @param e the element to add
jaroslav@1890
   442
     * @return {@code true} (as specified by {@link Collection#add})
jaroslav@1890
   443
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   444
     *         with elements currently in the priority queue according to the
jaroslav@1890
   445
     *         priority queue's ordering
jaroslav@1890
   446
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   447
     */
jaroslav@1890
   448
    public boolean add(E e) {
jaroslav@1890
   449
        return offer(e);
jaroslav@1890
   450
    }
jaroslav@1890
   451
jaroslav@1890
   452
    /**
jaroslav@1890
   453
     * Inserts the specified element into this priority queue.
jaroslav@1890
   454
     * As the queue is unbounded, this method will never return {@code false}.
jaroslav@1890
   455
     *
jaroslav@1890
   456
     * @param e the element to add
jaroslav@1890
   457
     * @return {@code true} (as specified by {@link Queue#offer})
jaroslav@1890
   458
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   459
     *         with elements currently in the priority queue according to the
jaroslav@1890
   460
     *         priority queue's ordering
jaroslav@1890
   461
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   462
     */
jaroslav@1890
   463
    public boolean offer(E e) {
jaroslav@1890
   464
        if (e == null)
jaroslav@1890
   465
            throw new NullPointerException();
jaroslav@1890
   466
        final ReentrantLock lock = this.lock;
jaroslav@1890
   467
        lock.lock();
jaroslav@1890
   468
        int n, cap;
jaroslav@1890
   469
        Object[] array;
jaroslav@1890
   470
        while ((n = size) >= (cap = (array = queue).length))
jaroslav@1890
   471
            tryGrow(array, cap);
jaroslav@1890
   472
        try {
jaroslav@1890
   473
            Comparator<? super E> cmp = comparator;
jaroslav@1890
   474
            if (cmp == null)
jaroslav@1890
   475
                siftUpComparable(n, e, array);
jaroslav@1890
   476
            else
jaroslav@1890
   477
                siftUpUsingComparator(n, e, array, cmp);
jaroslav@1890
   478
            size = n + 1;
jaroslav@1890
   479
            notEmpty.signal();
jaroslav@1890
   480
        } finally {
jaroslav@1890
   481
            lock.unlock();
jaroslav@1890
   482
        }
jaroslav@1890
   483
        return true;
jaroslav@1890
   484
    }
jaroslav@1890
   485
jaroslav@1890
   486
    /**
jaroslav@1890
   487
     * Inserts the specified element into this priority queue.
jaroslav@1890
   488
     * As the queue is unbounded, this method will never block.
jaroslav@1890
   489
     *
jaroslav@1890
   490
     * @param e the element to add
jaroslav@1890
   491
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   492
     *         with elements currently in the priority queue according to the
jaroslav@1890
   493
     *         priority queue's ordering
jaroslav@1890
   494
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   495
     */
jaroslav@1890
   496
    public void put(E e) {
jaroslav@1890
   497
        offer(e); // never need to block
jaroslav@1890
   498
    }
jaroslav@1890
   499
jaroslav@1890
   500
    /**
jaroslav@1890
   501
     * Inserts the specified element into this priority queue.
jaroslav@1890
   502
     * As the queue is unbounded, this method will never block or
jaroslav@1890
   503
     * return {@code false}.
jaroslav@1890
   504
     *
jaroslav@1890
   505
     * @param e the element to add
jaroslav@1890
   506
     * @param timeout This parameter is ignored as the method never blocks
jaroslav@1890
   507
     * @param unit This parameter is ignored as the method never blocks
jaroslav@1890
   508
     * @return {@code true} (as specified by
jaroslav@1890
   509
     *  {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
jaroslav@1890
   510
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   511
     *         with elements currently in the priority queue according to the
jaroslav@1890
   512
     *         priority queue's ordering
jaroslav@1890
   513
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   514
     */
jaroslav@1890
   515
    public boolean offer(E e, long timeout, TimeUnit unit) {
jaroslav@1890
   516
        return offer(e); // never need to block
jaroslav@1890
   517
    }
jaroslav@1890
   518
jaroslav@1890
   519
    public E poll() {
jaroslav@1890
   520
        final ReentrantLock lock = this.lock;
jaroslav@1890
   521
        lock.lock();
jaroslav@1890
   522
        E result;
jaroslav@1890
   523
        try {
jaroslav@1890
   524
            result = extract();
jaroslav@1890
   525
        } finally {
jaroslav@1890
   526
            lock.unlock();
jaroslav@1890
   527
        }
jaroslav@1890
   528
        return result;
jaroslav@1890
   529
    }
jaroslav@1890
   530
jaroslav@1890
   531
    public E take() throws InterruptedException {
jaroslav@1890
   532
        final ReentrantLock lock = this.lock;
jaroslav@1890
   533
        lock.lockInterruptibly();
jaroslav@1890
   534
        E result;
jaroslav@1890
   535
        try {
jaroslav@1890
   536
            while ( (result = extract()) == null)
jaroslav@1890
   537
                notEmpty.await();
jaroslav@1890
   538
        } finally {
jaroslav@1890
   539
            lock.unlock();
jaroslav@1890
   540
        }
jaroslav@1890
   541
        return result;
jaroslav@1890
   542
    }
jaroslav@1890
   543
jaroslav@1890
   544
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
jaroslav@1890
   545
        long nanos = unit.toNanos(timeout);
jaroslav@1890
   546
        final ReentrantLock lock = this.lock;
jaroslav@1890
   547
        lock.lockInterruptibly();
jaroslav@1890
   548
        E result;
jaroslav@1890
   549
        try {
jaroslav@1890
   550
            while ( (result = extract()) == null && nanos > 0)
jaroslav@1890
   551
                nanos = notEmpty.awaitNanos(nanos);
jaroslav@1890
   552
        } finally {
jaroslav@1890
   553
            lock.unlock();
jaroslav@1890
   554
        }
jaroslav@1890
   555
        return result;
jaroslav@1890
   556
    }
jaroslav@1890
   557
jaroslav@1890
   558
    public E peek() {
jaroslav@1890
   559
        final ReentrantLock lock = this.lock;
jaroslav@1890
   560
        lock.lock();
jaroslav@1890
   561
        E result;
jaroslav@1890
   562
        try {
jaroslav@1890
   563
            result = size > 0 ? (E) queue[0] : null;
jaroslav@1890
   564
        } finally {
jaroslav@1890
   565
            lock.unlock();
jaroslav@1890
   566
        }
jaroslav@1890
   567
        return result;
jaroslav@1890
   568
    }
jaroslav@1890
   569
jaroslav@1890
   570
    /**
jaroslav@1890
   571
     * Returns the comparator used to order the elements in this queue,
jaroslav@1890
   572
     * or {@code null} if this queue uses the {@linkplain Comparable
jaroslav@1890
   573
     * natural ordering} of its elements.
jaroslav@1890
   574
     *
jaroslav@1890
   575
     * @return the comparator used to order the elements in this queue,
jaroslav@1890
   576
     *         or {@code null} if this queue uses the natural
jaroslav@1890
   577
     *         ordering of its elements
jaroslav@1890
   578
     */
jaroslav@1890
   579
    public Comparator<? super E> comparator() {
jaroslav@1890
   580
        return comparator;
jaroslav@1890
   581
    }
jaroslav@1890
   582
jaroslav@1890
   583
    public int size() {
jaroslav@1890
   584
        final ReentrantLock lock = this.lock;
jaroslav@1890
   585
        lock.lock();
jaroslav@1890
   586
        try {
jaroslav@1890
   587
            return size;
jaroslav@1890
   588
        } finally {
jaroslav@1890
   589
            lock.unlock();
jaroslav@1890
   590
        }
jaroslav@1890
   591
    }
jaroslav@1890
   592
jaroslav@1890
   593
    /**
jaroslav@1890
   594
     * Always returns {@code Integer.MAX_VALUE} because
jaroslav@1890
   595
     * a {@code PriorityBlockingQueue} is not capacity constrained.
jaroslav@1890
   596
     * @return {@code Integer.MAX_VALUE} always
jaroslav@1890
   597
     */
jaroslav@1890
   598
    public int remainingCapacity() {
jaroslav@1890
   599
        return Integer.MAX_VALUE;
jaroslav@1890
   600
    }
jaroslav@1890
   601
jaroslav@1890
   602
    private int indexOf(Object o) {
jaroslav@1890
   603
        if (o != null) {
jaroslav@1890
   604
            Object[] array = queue;
jaroslav@1890
   605
            int n = size;
jaroslav@1890
   606
            for (int i = 0; i < n; i++)
jaroslav@1890
   607
                if (o.equals(array[i]))
jaroslav@1890
   608
                    return i;
jaroslav@1890
   609
        }
jaroslav@1890
   610
        return -1;
jaroslav@1890
   611
    }
jaroslav@1890
   612
jaroslav@1890
   613
    /**
jaroslav@1890
   614
     * Removes the ith element from queue.
jaroslav@1890
   615
     */
jaroslav@1890
   616
    private void removeAt(int i) {
jaroslav@1890
   617
        Object[] array = queue;
jaroslav@1890
   618
        int n = size - 1;
jaroslav@1890
   619
        if (n == i) // removed last element
jaroslav@1890
   620
            array[i] = null;
jaroslav@1890
   621
        else {
jaroslav@1890
   622
            E moved = (E) array[n];
jaroslav@1890
   623
            array[n] = null;
jaroslav@1890
   624
            Comparator<? super E> cmp = comparator;
jaroslav@1890
   625
            if (cmp == null)
jaroslav@1890
   626
                siftDownComparable(i, moved, array, n);
jaroslav@1890
   627
            else
jaroslav@1890
   628
                siftDownUsingComparator(i, moved, array, n, cmp);
jaroslav@1890
   629
            if (array[i] == moved) {
jaroslav@1890
   630
                if (cmp == null)
jaroslav@1890
   631
                    siftUpComparable(i, moved, array);
jaroslav@1890
   632
                else
jaroslav@1890
   633
                    siftUpUsingComparator(i, moved, array, cmp);
jaroslav@1890
   634
            }
jaroslav@1890
   635
        }
jaroslav@1890
   636
        size = n;
jaroslav@1890
   637
    }
jaroslav@1890
   638
jaroslav@1890
   639
    /**
jaroslav@1890
   640
     * Removes a single instance of the specified element from this queue,
jaroslav@1890
   641
     * if it is present.  More formally, removes an element {@code e} such
jaroslav@1890
   642
     * that {@code o.equals(e)}, if this queue contains one or more such
jaroslav@1890
   643
     * elements.  Returns {@code true} if and only if this queue contained
jaroslav@1890
   644
     * the specified element (or equivalently, if this queue changed as a
jaroslav@1890
   645
     * result of the call).
jaroslav@1890
   646
     *
jaroslav@1890
   647
     * @param o element to be removed from this queue, if present
jaroslav@1890
   648
     * @return {@code true} if this queue changed as a result of the call
jaroslav@1890
   649
     */
jaroslav@1890
   650
    public boolean remove(Object o) {
jaroslav@1890
   651
        boolean removed = false;
jaroslav@1890
   652
        final ReentrantLock lock = this.lock;
jaroslav@1890
   653
        lock.lock();
jaroslav@1890
   654
        try {
jaroslav@1890
   655
            int i = indexOf(o);
jaroslav@1890
   656
            if (i != -1) {
jaroslav@1890
   657
                removeAt(i);
jaroslav@1890
   658
                removed = true;
jaroslav@1890
   659
            }
jaroslav@1890
   660
        } finally {
jaroslav@1890
   661
            lock.unlock();
jaroslav@1890
   662
        }
jaroslav@1890
   663
        return removed;
jaroslav@1890
   664
    }
jaroslav@1890
   665
jaroslav@1890
   666
jaroslav@1890
   667
    /**
jaroslav@1890
   668
     * Identity-based version for use in Itr.remove
jaroslav@1890
   669
     */
jaroslav@1890
   670
    private void removeEQ(Object o) {
jaroslav@1890
   671
        final ReentrantLock lock = this.lock;
jaroslav@1890
   672
        lock.lock();
jaroslav@1890
   673
        try {
jaroslav@1890
   674
            Object[] array = queue;
jaroslav@1890
   675
            int n = size;
jaroslav@1890
   676
            for (int i = 0; i < n; i++) {
jaroslav@1890
   677
                if (o == array[i]) {
jaroslav@1890
   678
                    removeAt(i);
jaroslav@1890
   679
                    break;
jaroslav@1890
   680
                }
jaroslav@1890
   681
            }
jaroslav@1890
   682
        } finally {
jaroslav@1890
   683
            lock.unlock();
jaroslav@1890
   684
        }
jaroslav@1890
   685
    }
jaroslav@1890
   686
jaroslav@1890
   687
    /**
jaroslav@1890
   688
     * Returns {@code true} if this queue contains the specified element.
jaroslav@1890
   689
     * More formally, returns {@code true} if and only if this queue contains
jaroslav@1890
   690
     * at least one element {@code e} such that {@code o.equals(e)}.
jaroslav@1890
   691
     *
jaroslav@1890
   692
     * @param o object to be checked for containment in this queue
jaroslav@1890
   693
     * @return {@code true} if this queue contains the specified element
jaroslav@1890
   694
     */
jaroslav@1890
   695
    public boolean contains(Object o) {
jaroslav@1890
   696
        int index;
jaroslav@1890
   697
        final ReentrantLock lock = this.lock;
jaroslav@1890
   698
        lock.lock();
jaroslav@1890
   699
        try {
jaroslav@1890
   700
            index = indexOf(o);
jaroslav@1890
   701
        } finally {
jaroslav@1890
   702
            lock.unlock();
jaroslav@1890
   703
        }
jaroslav@1890
   704
        return index != -1;
jaroslav@1890
   705
    }
jaroslav@1890
   706
jaroslav@1890
   707
    /**
jaroslav@1890
   708
     * Returns an array containing all of the elements in this queue.
jaroslav@1890
   709
     * The returned array elements are in no particular order.
jaroslav@1890
   710
     *
jaroslav@1890
   711
     * <p>The returned array will be "safe" in that no references to it are
jaroslav@1890
   712
     * maintained by this queue.  (In other words, this method must allocate
jaroslav@1890
   713
     * a new array).  The caller is thus free to modify the returned array.
jaroslav@1890
   714
     *
jaroslav@1890
   715
     * <p>This method acts as bridge between array-based and collection-based
jaroslav@1890
   716
     * APIs.
jaroslav@1890
   717
     *
jaroslav@1890
   718
     * @return an array containing all of the elements in this queue
jaroslav@1890
   719
     */
jaroslav@1890
   720
    public Object[] toArray() {
jaroslav@1890
   721
        final ReentrantLock lock = this.lock;
jaroslav@1890
   722
        lock.lock();
jaroslav@1890
   723
        try {
jaroslav@1890
   724
            return Arrays.copyOf(queue, size);
jaroslav@1890
   725
        } finally {
jaroslav@1890
   726
            lock.unlock();
jaroslav@1890
   727
        }
jaroslav@1890
   728
    }
jaroslav@1890
   729
jaroslav@1890
   730
jaroslav@1890
   731
    public String toString() {
jaroslav@1890
   732
        final ReentrantLock lock = this.lock;
jaroslav@1890
   733
        lock.lock();
jaroslav@1890
   734
        try {
jaroslav@1890
   735
            int n = size;
jaroslav@1890
   736
            if (n == 0)
jaroslav@1890
   737
                return "[]";
jaroslav@1890
   738
            StringBuilder sb = new StringBuilder();
jaroslav@1890
   739
            sb.append('[');
jaroslav@1890
   740
            for (int i = 0; i < n; ++i) {
jaroslav@1890
   741
                E e = (E)queue[i];
jaroslav@1890
   742
                sb.append(e == this ? "(this Collection)" : e);
jaroslav@1890
   743
                if (i != n - 1)
jaroslav@1890
   744
                    sb.append(',').append(' ');
jaroslav@1890
   745
            }
jaroslav@1890
   746
            return sb.append(']').toString();
jaroslav@1890
   747
        } finally {
jaroslav@1890
   748
            lock.unlock();
jaroslav@1890
   749
        }
jaroslav@1890
   750
    }
jaroslav@1890
   751
jaroslav@1890
   752
    /**
jaroslav@1890
   753
     * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@1890
   754
     * @throws ClassCastException            {@inheritDoc}
jaroslav@1890
   755
     * @throws NullPointerException          {@inheritDoc}
jaroslav@1890
   756
     * @throws IllegalArgumentException      {@inheritDoc}
jaroslav@1890
   757
     */
jaroslav@1890
   758
    public int drainTo(Collection<? super E> c) {
jaroslav@1890
   759
        if (c == null)
jaroslav@1890
   760
            throw new NullPointerException();
jaroslav@1890
   761
        if (c == this)
jaroslav@1890
   762
            throw new IllegalArgumentException();
jaroslav@1890
   763
        final ReentrantLock lock = this.lock;
jaroslav@1890
   764
        lock.lock();
jaroslav@1890
   765
        try {
jaroslav@1890
   766
            int n = 0;
jaroslav@1890
   767
            E e;
jaroslav@1890
   768
            while ( (e = extract()) != null) {
jaroslav@1890
   769
                c.add(e);
jaroslav@1890
   770
                ++n;
jaroslav@1890
   771
            }
jaroslav@1890
   772
            return n;
jaroslav@1890
   773
        } finally {
jaroslav@1890
   774
            lock.unlock();
jaroslav@1890
   775
        }
jaroslav@1890
   776
    }
jaroslav@1890
   777
jaroslav@1890
   778
    /**
jaroslav@1890
   779
     * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@1890
   780
     * @throws ClassCastException            {@inheritDoc}
jaroslav@1890
   781
     * @throws NullPointerException          {@inheritDoc}
jaroslav@1890
   782
     * @throws IllegalArgumentException      {@inheritDoc}
jaroslav@1890
   783
     */
jaroslav@1890
   784
    public int drainTo(Collection<? super E> c, int maxElements) {
jaroslav@1890
   785
        if (c == null)
jaroslav@1890
   786
            throw new NullPointerException();
jaroslav@1890
   787
        if (c == this)
jaroslav@1890
   788
            throw new IllegalArgumentException();
jaroslav@1890
   789
        if (maxElements <= 0)
jaroslav@1890
   790
            return 0;
jaroslav@1890
   791
        final ReentrantLock lock = this.lock;
jaroslav@1890
   792
        lock.lock();
jaroslav@1890
   793
        try {
jaroslav@1890
   794
            int n = 0;
jaroslav@1890
   795
            E e;
jaroslav@1890
   796
            while (n < maxElements && (e = extract()) != null) {
jaroslav@1890
   797
                c.add(e);
jaroslav@1890
   798
                ++n;
jaroslav@1890
   799
            }
jaroslav@1890
   800
            return n;
jaroslav@1890
   801
        } finally {
jaroslav@1890
   802
            lock.unlock();
jaroslav@1890
   803
        }
jaroslav@1890
   804
    }
jaroslav@1890
   805
jaroslav@1890
   806
    /**
jaroslav@1890
   807
     * Atomically removes all of the elements from this queue.
jaroslav@1890
   808
     * The queue will be empty after this call returns.
jaroslav@1890
   809
     */
jaroslav@1890
   810
    public void clear() {
jaroslav@1890
   811
        final ReentrantLock lock = this.lock;
jaroslav@1890
   812
        lock.lock();
jaroslav@1890
   813
        try {
jaroslav@1890
   814
            Object[] array = queue;
jaroslav@1890
   815
            int n = size;
jaroslav@1890
   816
            size = 0;
jaroslav@1890
   817
            for (int i = 0; i < n; i++)
jaroslav@1890
   818
                array[i] = null;
jaroslav@1890
   819
        } finally {
jaroslav@1890
   820
            lock.unlock();
jaroslav@1890
   821
        }
jaroslav@1890
   822
    }
jaroslav@1890
   823
jaroslav@1890
   824
    /**
jaroslav@1890
   825
     * Returns an array containing all of the elements in this queue; the
jaroslav@1890
   826
     * runtime type of the returned array is that of the specified array.
jaroslav@1890
   827
     * The returned array elements are in no particular order.
jaroslav@1890
   828
     * If the queue fits in the specified array, it is returned therein.
jaroslav@1890
   829
     * Otherwise, a new array is allocated with the runtime type of the
jaroslav@1890
   830
     * specified array and the size of this queue.
jaroslav@1890
   831
     *
jaroslav@1890
   832
     * <p>If this queue fits in the specified array with room to spare
jaroslav@1890
   833
     * (i.e., the array has more elements than this queue), the element in
jaroslav@1890
   834
     * the array immediately following the end of the queue is set to
jaroslav@1890
   835
     * {@code null}.
jaroslav@1890
   836
     *
jaroslav@1890
   837
     * <p>Like the {@link #toArray()} method, this method acts as bridge between
jaroslav@1890
   838
     * array-based and collection-based APIs.  Further, this method allows
jaroslav@1890
   839
     * precise control over the runtime type of the output array, and may,
jaroslav@1890
   840
     * under certain circumstances, be used to save allocation costs.
jaroslav@1890
   841
     *
jaroslav@1890
   842
     * <p>Suppose {@code x} is a queue known to contain only strings.
jaroslav@1890
   843
     * The following code can be used to dump the queue into a newly
jaroslav@1890
   844
     * allocated array of {@code String}:
jaroslav@1890
   845
     *
jaroslav@1890
   846
     * <pre>
jaroslav@1890
   847
     *     String[] y = x.toArray(new String[0]);</pre>
jaroslav@1890
   848
     *
jaroslav@1890
   849
     * Note that {@code toArray(new Object[0])} is identical in function to
jaroslav@1890
   850
     * {@code toArray()}.
jaroslav@1890
   851
     *
jaroslav@1890
   852
     * @param a the array into which the elements of the queue are to
jaroslav@1890
   853
     *          be stored, if it is big enough; otherwise, a new array of the
jaroslav@1890
   854
     *          same runtime type is allocated for this purpose
jaroslav@1890
   855
     * @return an array containing all of the elements in this queue
jaroslav@1890
   856
     * @throws ArrayStoreException if the runtime type of the specified array
jaroslav@1890
   857
     *         is not a supertype of the runtime type of every element in
jaroslav@1890
   858
     *         this queue
jaroslav@1890
   859
     * @throws NullPointerException if the specified array is null
jaroslav@1890
   860
     */
jaroslav@1890
   861
    public <T> T[] toArray(T[] a) {
jaroslav@1890
   862
        final ReentrantLock lock = this.lock;
jaroslav@1890
   863
        lock.lock();
jaroslav@1890
   864
        try {
jaroslav@1890
   865
            int n = size;
jaroslav@1890
   866
            if (a.length < n)
jaroslav@1890
   867
                // Make a new array of a's runtime type, but my contents:
jaroslav@1890
   868
                return (T[]) Arrays.copyOf(queue, size, a.getClass());
jaroslav@1890
   869
            System.arraycopy(queue, 0, a, 0, n);
jaroslav@1890
   870
            if (a.length > n)
jaroslav@1890
   871
                a[n] = null;
jaroslav@1890
   872
            return a;
jaroslav@1890
   873
        } finally {
jaroslav@1890
   874
            lock.unlock();
jaroslav@1890
   875
        }
jaroslav@1890
   876
    }
jaroslav@1890
   877
jaroslav@1890
   878
    /**
jaroslav@1890
   879
     * Returns an iterator over the elements in this queue. The
jaroslav@1890
   880
     * iterator does not return the elements in any particular order.
jaroslav@1890
   881
     *
jaroslav@1890
   882
     * <p>The returned iterator is a "weakly consistent" iterator that
jaroslav@1890
   883
     * will never throw {@link java.util.ConcurrentModificationException
jaroslav@1890
   884
     * ConcurrentModificationException}, and guarantees to traverse
jaroslav@1890
   885
     * elements as they existed upon construction of the iterator, and
jaroslav@1890
   886
     * may (but is not guaranteed to) reflect any modifications
jaroslav@1890
   887
     * subsequent to construction.
jaroslav@1890
   888
     *
jaroslav@1890
   889
     * @return an iterator over the elements in this queue
jaroslav@1890
   890
     */
jaroslav@1890
   891
    public Iterator<E> iterator() {
jaroslav@1890
   892
        return new Itr(toArray());
jaroslav@1890
   893
    }
jaroslav@1890
   894
jaroslav@1890
   895
    /**
jaroslav@1890
   896
     * Snapshot iterator that works off copy of underlying q array.
jaroslav@1890
   897
     */
jaroslav@1890
   898
    final class Itr implements Iterator<E> {
jaroslav@1890
   899
        final Object[] array; // Array of all elements
jaroslav@1890
   900
        int cursor;           // index of next element to return;
jaroslav@1890
   901
        int lastRet;          // index of last element, or -1 if no such
jaroslav@1890
   902
jaroslav@1890
   903
        Itr(Object[] array) {
jaroslav@1890
   904
            lastRet = -1;
jaroslav@1890
   905
            this.array = array;
jaroslav@1890
   906
        }
jaroslav@1890
   907
jaroslav@1890
   908
        public boolean hasNext() {
jaroslav@1890
   909
            return cursor < array.length;
jaroslav@1890
   910
        }
jaroslav@1890
   911
jaroslav@1890
   912
        public E next() {
jaroslav@1890
   913
            if (cursor >= array.length)
jaroslav@1890
   914
                throw new NoSuchElementException();
jaroslav@1890
   915
            lastRet = cursor;
jaroslav@1890
   916
            return (E)array[cursor++];
jaroslav@1890
   917
        }
jaroslav@1890
   918
jaroslav@1890
   919
        public void remove() {
jaroslav@1890
   920
            if (lastRet < 0)
jaroslav@1890
   921
                throw new IllegalStateException();
jaroslav@1890
   922
            removeEQ(array[lastRet]);
jaroslav@1890
   923
            lastRet = -1;
jaroslav@1890
   924
        }
jaroslav@1890
   925
    }
jaroslav@1890
   926
jaroslav@1890
   927
    /**
jaroslav@1890
   928
     * Saves the state to a stream (that is, serializes it).  For
jaroslav@1890
   929
     * compatibility with previous version of this class,
jaroslav@1890
   930
     * elements are first copied to a java.util.PriorityQueue,
jaroslav@1890
   931
     * which is then serialized.
jaroslav@1890
   932
     */
jaroslav@1890
   933
    private void writeObject(java.io.ObjectOutputStream s)
jaroslav@1890
   934
        throws java.io.IOException {
jaroslav@1890
   935
        lock.lock();
jaroslav@1890
   936
        try {
jaroslav@1890
   937
            int n = size; // avoid zero capacity argument
jaroslav@1890
   938
            q = new PriorityQueue<E>(n == 0 ? 1 : n, comparator);
jaroslav@1890
   939
            q.addAll(this);
jaroslav@1890
   940
            s.defaultWriteObject();
jaroslav@1890
   941
        } finally {
jaroslav@1890
   942
            q = null;
jaroslav@1890
   943
            lock.unlock();
jaroslav@1890
   944
        }
jaroslav@1890
   945
    }
jaroslav@1890
   946
jaroslav@1890
   947
    /**
jaroslav@1890
   948
     * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream
jaroslav@1890
   949
     * (that is, deserializes it).
jaroslav@1890
   950
     *
jaroslav@1890
   951
     * @param s the stream
jaroslav@1890
   952
     */
jaroslav@1890
   953
    private void readObject(java.io.ObjectInputStream s)
jaroslav@1890
   954
        throws java.io.IOException, ClassNotFoundException {
jaroslav@1890
   955
        try {
jaroslav@1890
   956
            s.defaultReadObject();
jaroslav@1890
   957
            this.queue = new Object[q.size()];
jaroslav@1890
   958
            comparator = q.comparator();
jaroslav@1890
   959
            addAll(q);
jaroslav@1890
   960
        } finally {
jaroslav@1890
   961
            q = null;
jaroslav@1890
   962
        }
jaroslav@1890
   963
    }
jaroslav@1890
   964
jaroslav@1890
   965
    // Unsafe mechanics
jaroslav@1890
   966
    private static final sun.misc.Unsafe UNSAFE;
jaroslav@1890
   967
    private static final long allocationSpinLockOffset;
jaroslav@1890
   968
    static {
jaroslav@1890
   969
        try {
jaroslav@1890
   970
            UNSAFE = sun.misc.Unsafe.getUnsafe();
jaroslav@1890
   971
            Class k = PriorityBlockingQueue.class;
jaroslav@1890
   972
            allocationSpinLockOffset = UNSAFE.objectFieldOffset
jaroslav@1890
   973
                (k.getDeclaredField("allocationSpinLock"));
jaroslav@1890
   974
        } catch (Exception e) {
jaroslav@1890
   975
            throw new Error(e);
jaroslav@1890
   976
        }
jaroslav@1890
   977
    }
jaroslav@1890
   978
}