rt/emul/compact/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Sat, 19 Mar 2016 12:51:03 +0100
changeset 1895 bfaf3300b7ba
parent 1890 212417b74b72
permissions -rw-r--r--
Making java.util.concurrent package compilable except ForkJoinPool
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@1895
   279
        if (allocationSpinLock == 0) {
jaroslav@1895
   280
            allocationSpinLock = 1;
jaroslav@1890
   281
            try {
jaroslav@1890
   282
                int newCap = oldCap + ((oldCap < 64) ?
jaroslav@1890
   283
                                       (oldCap + 2) : // grow faster if small
jaroslav@1890
   284
                                       (oldCap >> 1));
jaroslav@1890
   285
                if (newCap - MAX_ARRAY_SIZE > 0) {    // possible overflow
jaroslav@1890
   286
                    int minCap = oldCap + 1;
jaroslav@1890
   287
                    if (minCap < 0 || minCap > MAX_ARRAY_SIZE)
jaroslav@1890
   288
                        throw new OutOfMemoryError();
jaroslav@1890
   289
                    newCap = MAX_ARRAY_SIZE;
jaroslav@1890
   290
                }
jaroslav@1890
   291
                if (newCap > oldCap && queue == array)
jaroslav@1890
   292
                    newArray = new Object[newCap];
jaroslav@1890
   293
            } finally {
jaroslav@1890
   294
                allocationSpinLock = 0;
jaroslav@1890
   295
            }
jaroslav@1890
   296
        }
jaroslav@1890
   297
        if (newArray == null) // back off if another thread is allocating
jaroslav@1890
   298
            Thread.yield();
jaroslav@1890
   299
        lock.lock();
jaroslav@1890
   300
        if (newArray != null && queue == array) {
jaroslav@1890
   301
            queue = newArray;
jaroslav@1890
   302
            System.arraycopy(array, 0, newArray, 0, oldCap);
jaroslav@1890
   303
        }
jaroslav@1890
   304
    }
jaroslav@1890
   305
jaroslav@1890
   306
    /**
jaroslav@1890
   307
     * Mechanics for poll().  Call only while holding lock.
jaroslav@1890
   308
     */
jaroslav@1890
   309
    private E extract() {
jaroslav@1890
   310
        E result;
jaroslav@1890
   311
        int n = size - 1;
jaroslav@1890
   312
        if (n < 0)
jaroslav@1890
   313
            result = null;
jaroslav@1890
   314
        else {
jaroslav@1890
   315
            Object[] array = queue;
jaroslav@1890
   316
            result = (E) array[0];
jaroslav@1890
   317
            E x = (E) array[n];
jaroslav@1890
   318
            array[n] = null;
jaroslav@1890
   319
            Comparator<? super E> cmp = comparator;
jaroslav@1890
   320
            if (cmp == null)
jaroslav@1890
   321
                siftDownComparable(0, x, array, n);
jaroslav@1890
   322
            else
jaroslav@1890
   323
                siftDownUsingComparator(0, x, array, n, cmp);
jaroslav@1890
   324
            size = n;
jaroslav@1890
   325
        }
jaroslav@1890
   326
        return result;
jaroslav@1890
   327
    }
jaroslav@1890
   328
jaroslav@1890
   329
    /**
jaroslav@1890
   330
     * Inserts item x at position k, maintaining heap invariant by
jaroslav@1890
   331
     * promoting x up the tree until it is greater than or equal to
jaroslav@1890
   332
     * its parent, or is the root.
jaroslav@1890
   333
     *
jaroslav@1890
   334
     * To simplify and speed up coercions and comparisons. the
jaroslav@1890
   335
     * Comparable and Comparator versions are separated into different
jaroslav@1890
   336
     * methods that are otherwise identical. (Similarly for siftDown.)
jaroslav@1890
   337
     * These methods are static, with heap state as arguments, to
jaroslav@1890
   338
     * simplify use in light of possible comparator exceptions.
jaroslav@1890
   339
     *
jaroslav@1890
   340
     * @param k the position to fill
jaroslav@1890
   341
     * @param x the item to insert
jaroslav@1890
   342
     * @param array the heap array
jaroslav@1890
   343
     * @param n heap size
jaroslav@1890
   344
     */
jaroslav@1890
   345
    private static <T> void siftUpComparable(int k, T x, Object[] array) {
jaroslav@1890
   346
        Comparable<? super T> key = (Comparable<? super T>) x;
jaroslav@1890
   347
        while (k > 0) {
jaroslav@1890
   348
            int parent = (k - 1) >>> 1;
jaroslav@1890
   349
            Object e = array[parent];
jaroslav@1890
   350
            if (key.compareTo((T) e) >= 0)
jaroslav@1890
   351
                break;
jaroslav@1890
   352
            array[k] = e;
jaroslav@1890
   353
            k = parent;
jaroslav@1890
   354
        }
jaroslav@1890
   355
        array[k] = key;
jaroslav@1890
   356
    }
jaroslav@1890
   357
jaroslav@1890
   358
    private static <T> void siftUpUsingComparator(int k, T x, Object[] array,
jaroslav@1890
   359
                                       Comparator<? super T> cmp) {
jaroslav@1890
   360
        while (k > 0) {
jaroslav@1890
   361
            int parent = (k - 1) >>> 1;
jaroslav@1890
   362
            Object e = array[parent];
jaroslav@1890
   363
            if (cmp.compare(x, (T) e) >= 0)
jaroslav@1890
   364
                break;
jaroslav@1890
   365
            array[k] = e;
jaroslav@1890
   366
            k = parent;
jaroslav@1890
   367
        }
jaroslav@1890
   368
        array[k] = x;
jaroslav@1890
   369
    }
jaroslav@1890
   370
jaroslav@1890
   371
    /**
jaroslav@1890
   372
     * Inserts item x at position k, maintaining heap invariant by
jaroslav@1890
   373
     * demoting x down the tree repeatedly until it is less than or
jaroslav@1890
   374
     * equal to its children or is a leaf.
jaroslav@1890
   375
     *
jaroslav@1890
   376
     * @param k the position to fill
jaroslav@1890
   377
     * @param x the item to insert
jaroslav@1890
   378
     * @param array the heap array
jaroslav@1890
   379
     * @param n heap size
jaroslav@1890
   380
     */
jaroslav@1890
   381
    private static <T> void siftDownComparable(int k, T x, Object[] array,
jaroslav@1890
   382
                                               int n) {
jaroslav@1890
   383
        Comparable<? super T> key = (Comparable<? super T>)x;
jaroslav@1890
   384
        int half = n >>> 1;           // loop while a non-leaf
jaroslav@1890
   385
        while (k < half) {
jaroslav@1890
   386
            int child = (k << 1) + 1; // assume left child is least
jaroslav@1890
   387
            Object c = array[child];
jaroslav@1890
   388
            int right = child + 1;
jaroslav@1890
   389
            if (right < n &&
jaroslav@1890
   390
                ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
jaroslav@1890
   391
                c = array[child = right];
jaroslav@1890
   392
            if (key.compareTo((T) c) <= 0)
jaroslav@1890
   393
                break;
jaroslav@1890
   394
            array[k] = c;
jaroslav@1890
   395
            k = child;
jaroslav@1890
   396
        }
jaroslav@1890
   397
        array[k] = key;
jaroslav@1890
   398
    }
jaroslav@1890
   399
jaroslav@1890
   400
    private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
jaroslav@1890
   401
                                                    int n,
jaroslav@1890
   402
                                                    Comparator<? super T> cmp) {
jaroslav@1890
   403
        int half = n >>> 1;
jaroslav@1890
   404
        while (k < half) {
jaroslav@1890
   405
            int child = (k << 1) + 1;
jaroslav@1890
   406
            Object c = array[child];
jaroslav@1890
   407
            int right = child + 1;
jaroslav@1890
   408
            if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
jaroslav@1890
   409
                c = array[child = right];
jaroslav@1890
   410
            if (cmp.compare(x, (T) c) <= 0)
jaroslav@1890
   411
                break;
jaroslav@1890
   412
            array[k] = c;
jaroslav@1890
   413
            k = child;
jaroslav@1890
   414
        }
jaroslav@1890
   415
        array[k] = x;
jaroslav@1890
   416
    }
jaroslav@1890
   417
jaroslav@1890
   418
    /**
jaroslav@1890
   419
     * Establishes the heap invariant (described above) in the entire tree,
jaroslav@1890
   420
     * assuming nothing about the order of the elements prior to the call.
jaroslav@1890
   421
     */
jaroslav@1890
   422
    private void heapify() {
jaroslav@1890
   423
        Object[] array = queue;
jaroslav@1890
   424
        int n = size;
jaroslav@1890
   425
        int half = (n >>> 1) - 1;
jaroslav@1890
   426
        Comparator<? super E> cmp = comparator;
jaroslav@1890
   427
        if (cmp == null) {
jaroslav@1890
   428
            for (int i = half; i >= 0; i--)
jaroslav@1890
   429
                siftDownComparable(i, (E) array[i], array, n);
jaroslav@1890
   430
        }
jaroslav@1890
   431
        else {
jaroslav@1890
   432
            for (int i = half; i >= 0; i--)
jaroslav@1890
   433
                siftDownUsingComparator(i, (E) array[i], array, n, cmp);
jaroslav@1890
   434
        }
jaroslav@1890
   435
    }
jaroslav@1890
   436
jaroslav@1890
   437
    /**
jaroslav@1890
   438
     * Inserts the specified element into this priority queue.
jaroslav@1890
   439
     *
jaroslav@1890
   440
     * @param e the element to add
jaroslav@1890
   441
     * @return {@code true} (as specified by {@link Collection#add})
jaroslav@1890
   442
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   443
     *         with elements currently in the priority queue according to the
jaroslav@1890
   444
     *         priority queue's ordering
jaroslav@1890
   445
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   446
     */
jaroslav@1890
   447
    public boolean add(E e) {
jaroslav@1890
   448
        return offer(e);
jaroslav@1890
   449
    }
jaroslav@1890
   450
jaroslav@1890
   451
    /**
jaroslav@1890
   452
     * Inserts the specified element into this priority queue.
jaroslav@1890
   453
     * As the queue is unbounded, this method will never return {@code false}.
jaroslav@1890
   454
     *
jaroslav@1890
   455
     * @param e the element to add
jaroslav@1890
   456
     * @return {@code true} (as specified by {@link Queue#offer})
jaroslav@1890
   457
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   458
     *         with elements currently in the priority queue according to the
jaroslav@1890
   459
     *         priority queue's ordering
jaroslav@1890
   460
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   461
     */
jaroslav@1890
   462
    public boolean offer(E e) {
jaroslav@1890
   463
        if (e == null)
jaroslav@1890
   464
            throw new NullPointerException();
jaroslav@1890
   465
        final ReentrantLock lock = this.lock;
jaroslav@1890
   466
        lock.lock();
jaroslav@1890
   467
        int n, cap;
jaroslav@1890
   468
        Object[] array;
jaroslav@1890
   469
        while ((n = size) >= (cap = (array = queue).length))
jaroslav@1890
   470
            tryGrow(array, cap);
jaroslav@1890
   471
        try {
jaroslav@1890
   472
            Comparator<? super E> cmp = comparator;
jaroslav@1890
   473
            if (cmp == null)
jaroslav@1890
   474
                siftUpComparable(n, e, array);
jaroslav@1890
   475
            else
jaroslav@1890
   476
                siftUpUsingComparator(n, e, array, cmp);
jaroslav@1890
   477
            size = n + 1;
jaroslav@1890
   478
            notEmpty.signal();
jaroslav@1890
   479
        } finally {
jaroslav@1890
   480
            lock.unlock();
jaroslav@1890
   481
        }
jaroslav@1890
   482
        return true;
jaroslav@1890
   483
    }
jaroslav@1890
   484
jaroslav@1890
   485
    /**
jaroslav@1890
   486
     * Inserts the specified element into this priority queue.
jaroslav@1890
   487
     * As the queue is unbounded, this method will never block.
jaroslav@1890
   488
     *
jaroslav@1890
   489
     * @param e the element to add
jaroslav@1890
   490
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   491
     *         with elements currently in the priority queue according to the
jaroslav@1890
   492
     *         priority queue's ordering
jaroslav@1890
   493
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   494
     */
jaroslav@1890
   495
    public void put(E e) {
jaroslav@1890
   496
        offer(e); // never need to block
jaroslav@1890
   497
    }
jaroslav@1890
   498
jaroslav@1890
   499
    /**
jaroslav@1890
   500
     * Inserts the specified element into this priority queue.
jaroslav@1890
   501
     * As the queue is unbounded, this method will never block or
jaroslav@1890
   502
     * return {@code false}.
jaroslav@1890
   503
     *
jaroslav@1890
   504
     * @param e the element to add
jaroslav@1890
   505
     * @param timeout This parameter is ignored as the method never blocks
jaroslav@1890
   506
     * @param unit This parameter is ignored as the method never blocks
jaroslav@1890
   507
     * @return {@code true} (as specified by
jaroslav@1890
   508
     *  {@link BlockingQueue#offer(Object,long,TimeUnit) BlockingQueue.offer})
jaroslav@1890
   509
     * @throws ClassCastException if the specified element cannot be compared
jaroslav@1890
   510
     *         with elements currently in the priority queue according to the
jaroslav@1890
   511
     *         priority queue's ordering
jaroslav@1890
   512
     * @throws NullPointerException if the specified element is null
jaroslav@1890
   513
     */
jaroslav@1890
   514
    public boolean offer(E e, long timeout, TimeUnit unit) {
jaroslav@1890
   515
        return offer(e); // never need to block
jaroslav@1890
   516
    }
jaroslav@1890
   517
jaroslav@1890
   518
    public E poll() {
jaroslav@1890
   519
        final ReentrantLock lock = this.lock;
jaroslav@1890
   520
        lock.lock();
jaroslav@1890
   521
        E result;
jaroslav@1890
   522
        try {
jaroslav@1890
   523
            result = extract();
jaroslav@1890
   524
        } finally {
jaroslav@1890
   525
            lock.unlock();
jaroslav@1890
   526
        }
jaroslav@1890
   527
        return result;
jaroslav@1890
   528
    }
jaroslav@1890
   529
jaroslav@1890
   530
    public E take() throws InterruptedException {
jaroslav@1890
   531
        final ReentrantLock lock = this.lock;
jaroslav@1890
   532
        lock.lockInterruptibly();
jaroslav@1890
   533
        E result;
jaroslav@1890
   534
        try {
jaroslav@1890
   535
            while ( (result = extract()) == null)
jaroslav@1890
   536
                notEmpty.await();
jaroslav@1890
   537
        } finally {
jaroslav@1890
   538
            lock.unlock();
jaroslav@1890
   539
        }
jaroslav@1890
   540
        return result;
jaroslav@1890
   541
    }
jaroslav@1890
   542
jaroslav@1890
   543
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
jaroslav@1890
   544
        long nanos = unit.toNanos(timeout);
jaroslav@1890
   545
        final ReentrantLock lock = this.lock;
jaroslav@1890
   546
        lock.lockInterruptibly();
jaroslav@1890
   547
        E result;
jaroslav@1890
   548
        try {
jaroslav@1890
   549
            while ( (result = extract()) == null && nanos > 0)
jaroslav@1890
   550
                nanos = notEmpty.awaitNanos(nanos);
jaroslav@1890
   551
        } finally {
jaroslav@1890
   552
            lock.unlock();
jaroslav@1890
   553
        }
jaroslav@1890
   554
        return result;
jaroslav@1890
   555
    }
jaroslav@1890
   556
jaroslav@1890
   557
    public E peek() {
jaroslav@1890
   558
        final ReentrantLock lock = this.lock;
jaroslav@1890
   559
        lock.lock();
jaroslav@1890
   560
        E result;
jaroslav@1890
   561
        try {
jaroslav@1890
   562
            result = size > 0 ? (E) queue[0] : null;
jaroslav@1890
   563
        } finally {
jaroslav@1890
   564
            lock.unlock();
jaroslav@1890
   565
        }
jaroslav@1890
   566
        return result;
jaroslav@1890
   567
    }
jaroslav@1890
   568
jaroslav@1890
   569
    /**
jaroslav@1890
   570
     * Returns the comparator used to order the elements in this queue,
jaroslav@1890
   571
     * or {@code null} if this queue uses the {@linkplain Comparable
jaroslav@1890
   572
     * natural ordering} of its elements.
jaroslav@1890
   573
     *
jaroslav@1890
   574
     * @return the comparator used to order the elements in this queue,
jaroslav@1890
   575
     *         or {@code null} if this queue uses the natural
jaroslav@1890
   576
     *         ordering of its elements
jaroslav@1890
   577
     */
jaroslav@1890
   578
    public Comparator<? super E> comparator() {
jaroslav@1890
   579
        return comparator;
jaroslav@1890
   580
    }
jaroslav@1890
   581
jaroslav@1890
   582
    public int size() {
jaroslav@1890
   583
        final ReentrantLock lock = this.lock;
jaroslav@1890
   584
        lock.lock();
jaroslav@1890
   585
        try {
jaroslav@1890
   586
            return size;
jaroslav@1890
   587
        } finally {
jaroslav@1890
   588
            lock.unlock();
jaroslav@1890
   589
        }
jaroslav@1890
   590
    }
jaroslav@1890
   591
jaroslav@1890
   592
    /**
jaroslav@1890
   593
     * Always returns {@code Integer.MAX_VALUE} because
jaroslav@1890
   594
     * a {@code PriorityBlockingQueue} is not capacity constrained.
jaroslav@1890
   595
     * @return {@code Integer.MAX_VALUE} always
jaroslav@1890
   596
     */
jaroslav@1890
   597
    public int remainingCapacity() {
jaroslav@1890
   598
        return Integer.MAX_VALUE;
jaroslav@1890
   599
    }
jaroslav@1890
   600
jaroslav@1890
   601
    private int indexOf(Object o) {
jaroslav@1890
   602
        if (o != null) {
jaroslav@1890
   603
            Object[] array = queue;
jaroslav@1890
   604
            int n = size;
jaroslav@1890
   605
            for (int i = 0; i < n; i++)
jaroslav@1890
   606
                if (o.equals(array[i]))
jaroslav@1890
   607
                    return i;
jaroslav@1890
   608
        }
jaroslav@1890
   609
        return -1;
jaroslav@1890
   610
    }
jaroslav@1890
   611
jaroslav@1890
   612
    /**
jaroslav@1890
   613
     * Removes the ith element from queue.
jaroslav@1890
   614
     */
jaroslav@1890
   615
    private void removeAt(int i) {
jaroslav@1890
   616
        Object[] array = queue;
jaroslav@1890
   617
        int n = size - 1;
jaroslav@1890
   618
        if (n == i) // removed last element
jaroslav@1890
   619
            array[i] = null;
jaroslav@1890
   620
        else {
jaroslav@1890
   621
            E moved = (E) array[n];
jaroslav@1890
   622
            array[n] = null;
jaroslav@1890
   623
            Comparator<? super E> cmp = comparator;
jaroslav@1890
   624
            if (cmp == null)
jaroslav@1890
   625
                siftDownComparable(i, moved, array, n);
jaroslav@1890
   626
            else
jaroslav@1890
   627
                siftDownUsingComparator(i, moved, array, n, cmp);
jaroslav@1890
   628
            if (array[i] == moved) {
jaroslav@1890
   629
                if (cmp == null)
jaroslav@1890
   630
                    siftUpComparable(i, moved, array);
jaroslav@1890
   631
                else
jaroslav@1890
   632
                    siftUpUsingComparator(i, moved, array, cmp);
jaroslav@1890
   633
            }
jaroslav@1890
   634
        }
jaroslav@1890
   635
        size = n;
jaroslav@1890
   636
    }
jaroslav@1890
   637
jaroslav@1890
   638
    /**
jaroslav@1890
   639
     * Removes a single instance of the specified element from this queue,
jaroslav@1890
   640
     * if it is present.  More formally, removes an element {@code e} such
jaroslav@1890
   641
     * that {@code o.equals(e)}, if this queue contains one or more such
jaroslav@1890
   642
     * elements.  Returns {@code true} if and only if this queue contained
jaroslav@1890
   643
     * the specified element (or equivalently, if this queue changed as a
jaroslav@1890
   644
     * result of the call).
jaroslav@1890
   645
     *
jaroslav@1890
   646
     * @param o element to be removed from this queue, if present
jaroslav@1890
   647
     * @return {@code true} if this queue changed as a result of the call
jaroslav@1890
   648
     */
jaroslav@1890
   649
    public boolean remove(Object o) {
jaroslav@1890
   650
        boolean removed = false;
jaroslav@1890
   651
        final ReentrantLock lock = this.lock;
jaroslav@1890
   652
        lock.lock();
jaroslav@1890
   653
        try {
jaroslav@1890
   654
            int i = indexOf(o);
jaroslav@1890
   655
            if (i != -1) {
jaroslav@1890
   656
                removeAt(i);
jaroslav@1890
   657
                removed = true;
jaroslav@1890
   658
            }
jaroslav@1890
   659
        } finally {
jaroslav@1890
   660
            lock.unlock();
jaroslav@1890
   661
        }
jaroslav@1890
   662
        return removed;
jaroslav@1890
   663
    }
jaroslav@1890
   664
jaroslav@1890
   665
jaroslav@1890
   666
    /**
jaroslav@1890
   667
     * Identity-based version for use in Itr.remove
jaroslav@1890
   668
     */
jaroslav@1890
   669
    private void removeEQ(Object o) {
jaroslav@1890
   670
        final ReentrantLock lock = this.lock;
jaroslav@1890
   671
        lock.lock();
jaroslav@1890
   672
        try {
jaroslav@1890
   673
            Object[] array = queue;
jaroslav@1890
   674
            int n = size;
jaroslav@1890
   675
            for (int i = 0; i < n; i++) {
jaroslav@1890
   676
                if (o == array[i]) {
jaroslav@1890
   677
                    removeAt(i);
jaroslav@1890
   678
                    break;
jaroslav@1890
   679
                }
jaroslav@1890
   680
            }
jaroslav@1890
   681
        } finally {
jaroslav@1890
   682
            lock.unlock();
jaroslav@1890
   683
        }
jaroslav@1890
   684
    }
jaroslav@1890
   685
jaroslav@1890
   686
    /**
jaroslav@1890
   687
     * Returns {@code true} if this queue contains the specified element.
jaroslav@1890
   688
     * More formally, returns {@code true} if and only if this queue contains
jaroslav@1890
   689
     * at least one element {@code e} such that {@code o.equals(e)}.
jaroslav@1890
   690
     *
jaroslav@1890
   691
     * @param o object to be checked for containment in this queue
jaroslav@1890
   692
     * @return {@code true} if this queue contains the specified element
jaroslav@1890
   693
     */
jaroslav@1890
   694
    public boolean contains(Object o) {
jaroslav@1890
   695
        int index;
jaroslav@1890
   696
        final ReentrantLock lock = this.lock;
jaroslav@1890
   697
        lock.lock();
jaroslav@1890
   698
        try {
jaroslav@1890
   699
            index = indexOf(o);
jaroslav@1890
   700
        } finally {
jaroslav@1890
   701
            lock.unlock();
jaroslav@1890
   702
        }
jaroslav@1890
   703
        return index != -1;
jaroslav@1890
   704
    }
jaroslav@1890
   705
jaroslav@1890
   706
    /**
jaroslav@1890
   707
     * Returns an array containing all of the elements in this queue.
jaroslav@1890
   708
     * The returned array elements are in no particular order.
jaroslav@1890
   709
     *
jaroslav@1890
   710
     * <p>The returned array will be "safe" in that no references to it are
jaroslav@1890
   711
     * maintained by this queue.  (In other words, this method must allocate
jaroslav@1890
   712
     * a new array).  The caller is thus free to modify the returned array.
jaroslav@1890
   713
     *
jaroslav@1890
   714
     * <p>This method acts as bridge between array-based and collection-based
jaroslav@1890
   715
     * APIs.
jaroslav@1890
   716
     *
jaroslav@1890
   717
     * @return an array containing all of the elements in this queue
jaroslav@1890
   718
     */
jaroslav@1890
   719
    public Object[] toArray() {
jaroslav@1890
   720
        final ReentrantLock lock = this.lock;
jaroslav@1890
   721
        lock.lock();
jaroslav@1890
   722
        try {
jaroslav@1890
   723
            return Arrays.copyOf(queue, size);
jaroslav@1890
   724
        } finally {
jaroslav@1890
   725
            lock.unlock();
jaroslav@1890
   726
        }
jaroslav@1890
   727
    }
jaroslav@1890
   728
jaroslav@1890
   729
jaroslav@1890
   730
    public String toString() {
jaroslav@1890
   731
        final ReentrantLock lock = this.lock;
jaroslav@1890
   732
        lock.lock();
jaroslav@1890
   733
        try {
jaroslav@1890
   734
            int n = size;
jaroslav@1890
   735
            if (n == 0)
jaroslav@1890
   736
                return "[]";
jaroslav@1890
   737
            StringBuilder sb = new StringBuilder();
jaroslav@1890
   738
            sb.append('[');
jaroslav@1890
   739
            for (int i = 0; i < n; ++i) {
jaroslav@1890
   740
                E e = (E)queue[i];
jaroslav@1890
   741
                sb.append(e == this ? "(this Collection)" : e);
jaroslav@1890
   742
                if (i != n - 1)
jaroslav@1890
   743
                    sb.append(',').append(' ');
jaroslav@1890
   744
            }
jaroslav@1890
   745
            return sb.append(']').toString();
jaroslav@1890
   746
        } finally {
jaroslav@1890
   747
            lock.unlock();
jaroslav@1890
   748
        }
jaroslav@1890
   749
    }
jaroslav@1890
   750
jaroslav@1890
   751
    /**
jaroslav@1890
   752
     * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@1890
   753
     * @throws ClassCastException            {@inheritDoc}
jaroslav@1890
   754
     * @throws NullPointerException          {@inheritDoc}
jaroslav@1890
   755
     * @throws IllegalArgumentException      {@inheritDoc}
jaroslav@1890
   756
     */
jaroslav@1890
   757
    public int drainTo(Collection<? super E> c) {
jaroslav@1890
   758
        if (c == null)
jaroslav@1890
   759
            throw new NullPointerException();
jaroslav@1890
   760
        if (c == this)
jaroslav@1890
   761
            throw new IllegalArgumentException();
jaroslav@1890
   762
        final ReentrantLock lock = this.lock;
jaroslav@1890
   763
        lock.lock();
jaroslav@1890
   764
        try {
jaroslav@1890
   765
            int n = 0;
jaroslav@1890
   766
            E e;
jaroslav@1890
   767
            while ( (e = extract()) != null) {
jaroslav@1890
   768
                c.add(e);
jaroslav@1890
   769
                ++n;
jaroslav@1890
   770
            }
jaroslav@1890
   771
            return n;
jaroslav@1890
   772
        } finally {
jaroslav@1890
   773
            lock.unlock();
jaroslav@1890
   774
        }
jaroslav@1890
   775
    }
jaroslav@1890
   776
jaroslav@1890
   777
    /**
jaroslav@1890
   778
     * @throws UnsupportedOperationException {@inheritDoc}
jaroslav@1890
   779
     * @throws ClassCastException            {@inheritDoc}
jaroslav@1890
   780
     * @throws NullPointerException          {@inheritDoc}
jaroslav@1890
   781
     * @throws IllegalArgumentException      {@inheritDoc}
jaroslav@1890
   782
     */
jaroslav@1890
   783
    public int drainTo(Collection<? super E> c, int maxElements) {
jaroslav@1890
   784
        if (c == null)
jaroslav@1890
   785
            throw new NullPointerException();
jaroslav@1890
   786
        if (c == this)
jaroslav@1890
   787
            throw new IllegalArgumentException();
jaroslav@1890
   788
        if (maxElements <= 0)
jaroslav@1890
   789
            return 0;
jaroslav@1890
   790
        final ReentrantLock lock = this.lock;
jaroslav@1890
   791
        lock.lock();
jaroslav@1890
   792
        try {
jaroslav@1890
   793
            int n = 0;
jaroslav@1890
   794
            E e;
jaroslav@1890
   795
            while (n < maxElements && (e = extract()) != null) {
jaroslav@1890
   796
                c.add(e);
jaroslav@1890
   797
                ++n;
jaroslav@1890
   798
            }
jaroslav@1890
   799
            return n;
jaroslav@1890
   800
        } finally {
jaroslav@1890
   801
            lock.unlock();
jaroslav@1890
   802
        }
jaroslav@1890
   803
    }
jaroslav@1890
   804
jaroslav@1890
   805
    /**
jaroslav@1890
   806
     * Atomically removes all of the elements from this queue.
jaroslav@1890
   807
     * The queue will be empty after this call returns.
jaroslav@1890
   808
     */
jaroslav@1890
   809
    public void clear() {
jaroslav@1890
   810
        final ReentrantLock lock = this.lock;
jaroslav@1890
   811
        lock.lock();
jaroslav@1890
   812
        try {
jaroslav@1890
   813
            Object[] array = queue;
jaroslav@1890
   814
            int n = size;
jaroslav@1890
   815
            size = 0;
jaroslav@1890
   816
            for (int i = 0; i < n; i++)
jaroslav@1890
   817
                array[i] = null;
jaroslav@1890
   818
        } finally {
jaroslav@1890
   819
            lock.unlock();
jaroslav@1890
   820
        }
jaroslav@1890
   821
    }
jaroslav@1890
   822
jaroslav@1890
   823
    /**
jaroslav@1890
   824
     * Returns an array containing all of the elements in this queue; the
jaroslav@1890
   825
     * runtime type of the returned array is that of the specified array.
jaroslav@1890
   826
     * The returned array elements are in no particular order.
jaroslav@1890
   827
     * If the queue fits in the specified array, it is returned therein.
jaroslav@1890
   828
     * Otherwise, a new array is allocated with the runtime type of the
jaroslav@1890
   829
     * specified array and the size of this queue.
jaroslav@1890
   830
     *
jaroslav@1890
   831
     * <p>If this queue fits in the specified array with room to spare
jaroslav@1890
   832
     * (i.e., the array has more elements than this queue), the element in
jaroslav@1890
   833
     * the array immediately following the end of the queue is set to
jaroslav@1890
   834
     * {@code null}.
jaroslav@1890
   835
     *
jaroslav@1890
   836
     * <p>Like the {@link #toArray()} method, this method acts as bridge between
jaroslav@1890
   837
     * array-based and collection-based APIs.  Further, this method allows
jaroslav@1890
   838
     * precise control over the runtime type of the output array, and may,
jaroslav@1890
   839
     * under certain circumstances, be used to save allocation costs.
jaroslav@1890
   840
     *
jaroslav@1890
   841
     * <p>Suppose {@code x} is a queue known to contain only strings.
jaroslav@1890
   842
     * The following code can be used to dump the queue into a newly
jaroslav@1890
   843
     * allocated array of {@code String}:
jaroslav@1890
   844
     *
jaroslav@1890
   845
     * <pre>
jaroslav@1890
   846
     *     String[] y = x.toArray(new String[0]);</pre>
jaroslav@1890
   847
     *
jaroslav@1890
   848
     * Note that {@code toArray(new Object[0])} is identical in function to
jaroslav@1890
   849
     * {@code toArray()}.
jaroslav@1890
   850
     *
jaroslav@1890
   851
     * @param a the array into which the elements of the queue are to
jaroslav@1890
   852
     *          be stored, if it is big enough; otherwise, a new array of the
jaroslav@1890
   853
     *          same runtime type is allocated for this purpose
jaroslav@1890
   854
     * @return an array containing all of the elements in this queue
jaroslav@1890
   855
     * @throws ArrayStoreException if the runtime type of the specified array
jaroslav@1890
   856
     *         is not a supertype of the runtime type of every element in
jaroslav@1890
   857
     *         this queue
jaroslav@1890
   858
     * @throws NullPointerException if the specified array is null
jaroslav@1890
   859
     */
jaroslav@1890
   860
    public <T> T[] toArray(T[] a) {
jaroslav@1890
   861
        final ReentrantLock lock = this.lock;
jaroslav@1890
   862
        lock.lock();
jaroslav@1890
   863
        try {
jaroslav@1890
   864
            int n = size;
jaroslav@1890
   865
            if (a.length < n)
jaroslav@1890
   866
                // Make a new array of a's runtime type, but my contents:
jaroslav@1890
   867
                return (T[]) Arrays.copyOf(queue, size, a.getClass());
jaroslav@1890
   868
            System.arraycopy(queue, 0, a, 0, n);
jaroslav@1890
   869
            if (a.length > n)
jaroslav@1890
   870
                a[n] = null;
jaroslav@1890
   871
            return a;
jaroslav@1890
   872
        } finally {
jaroslav@1890
   873
            lock.unlock();
jaroslav@1890
   874
        }
jaroslav@1890
   875
    }
jaroslav@1890
   876
jaroslav@1890
   877
    /**
jaroslav@1890
   878
     * Returns an iterator over the elements in this queue. The
jaroslav@1890
   879
     * iterator does not return the elements in any particular order.
jaroslav@1890
   880
     *
jaroslav@1890
   881
     * <p>The returned iterator is a "weakly consistent" iterator that
jaroslav@1890
   882
     * will never throw {@link java.util.ConcurrentModificationException
jaroslav@1890
   883
     * ConcurrentModificationException}, and guarantees to traverse
jaroslav@1890
   884
     * elements as they existed upon construction of the iterator, and
jaroslav@1890
   885
     * may (but is not guaranteed to) reflect any modifications
jaroslav@1890
   886
     * subsequent to construction.
jaroslav@1890
   887
     *
jaroslav@1890
   888
     * @return an iterator over the elements in this queue
jaroslav@1890
   889
     */
jaroslav@1890
   890
    public Iterator<E> iterator() {
jaroslav@1890
   891
        return new Itr(toArray());
jaroslav@1890
   892
    }
jaroslav@1890
   893
jaroslav@1890
   894
    /**
jaroslav@1890
   895
     * Snapshot iterator that works off copy of underlying q array.
jaroslav@1890
   896
     */
jaroslav@1890
   897
    final class Itr implements Iterator<E> {
jaroslav@1890
   898
        final Object[] array; // Array of all elements
jaroslav@1890
   899
        int cursor;           // index of next element to return;
jaroslav@1890
   900
        int lastRet;          // index of last element, or -1 if no such
jaroslav@1890
   901
jaroslav@1890
   902
        Itr(Object[] array) {
jaroslav@1890
   903
            lastRet = -1;
jaroslav@1890
   904
            this.array = array;
jaroslav@1890
   905
        }
jaroslav@1890
   906
jaroslav@1890
   907
        public boolean hasNext() {
jaroslav@1890
   908
            return cursor < array.length;
jaroslav@1890
   909
        }
jaroslav@1890
   910
jaroslav@1890
   911
        public E next() {
jaroslav@1890
   912
            if (cursor >= array.length)
jaroslav@1890
   913
                throw new NoSuchElementException();
jaroslav@1890
   914
            lastRet = cursor;
jaroslav@1890
   915
            return (E)array[cursor++];
jaroslav@1890
   916
        }
jaroslav@1890
   917
jaroslav@1890
   918
        public void remove() {
jaroslav@1890
   919
            if (lastRet < 0)
jaroslav@1890
   920
                throw new IllegalStateException();
jaroslav@1890
   921
            removeEQ(array[lastRet]);
jaroslav@1890
   922
            lastRet = -1;
jaroslav@1890
   923
        }
jaroslav@1890
   924
    }
jaroslav@1890
   925
jaroslav@1890
   926
    /**
jaroslav@1890
   927
     * Saves the state to a stream (that is, serializes it).  For
jaroslav@1890
   928
     * compatibility with previous version of this class,
jaroslav@1890
   929
     * elements are first copied to a java.util.PriorityQueue,
jaroslav@1890
   930
     * which is then serialized.
jaroslav@1890
   931
     */
jaroslav@1890
   932
    private void writeObject(java.io.ObjectOutputStream s)
jaroslav@1890
   933
        throws java.io.IOException {
jaroslav@1890
   934
        lock.lock();
jaroslav@1890
   935
        try {
jaroslav@1890
   936
            int n = size; // avoid zero capacity argument
jaroslav@1890
   937
            q = new PriorityQueue<E>(n == 0 ? 1 : n, comparator);
jaroslav@1890
   938
            q.addAll(this);
jaroslav@1890
   939
            s.defaultWriteObject();
jaroslav@1890
   940
        } finally {
jaroslav@1890
   941
            q = null;
jaroslav@1890
   942
            lock.unlock();
jaroslav@1890
   943
        }
jaroslav@1890
   944
    }
jaroslav@1890
   945
jaroslav@1890
   946
    /**
jaroslav@1890
   947
     * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream
jaroslav@1890
   948
     * (that is, deserializes it).
jaroslav@1890
   949
     *
jaroslav@1890
   950
     * @param s the stream
jaroslav@1890
   951
     */
jaroslav@1890
   952
    private void readObject(java.io.ObjectInputStream s)
jaroslav@1890
   953
        throws java.io.IOException, ClassNotFoundException {
jaroslav@1890
   954
        try {
jaroslav@1890
   955
            s.defaultReadObject();
jaroslav@1890
   956
            this.queue = new Object[q.size()];
jaroslav@1890
   957
            comparator = q.comparator();
jaroslav@1890
   958
            addAll(q);
jaroslav@1890
   959
        } finally {
jaroslav@1890
   960
            q = null;
jaroslav@1890
   961
        }
jaroslav@1890
   962
    }
jaroslav@1890
   963
}