ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/PriorityBlockingQueue.java
Revision: 1.142
Committed: Thu Oct 17 01:51:38 2019 UTC (4 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.141: +1 -0 lines
Log Message:
8232230: Suppress warnings on non-serializable non-transient instance fields in java.util.concurrent

File Contents

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