ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/PriorityBlockingQueue.java
Revision: 1.64
Committed: Mon Oct 11 18:10:18 2010 UTC (13 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.63: +6 -4 lines
Log Message:
sync javadoc of enqueue methods

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