262 this.comparator = (Comparator<? super E>) pq.comparator(); |
259 this.comparator = (Comparator<? super E>) pq.comparator(); |
263 screen = false; |
260 screen = false; |
264 if (pq.getClass() == PriorityBlockingQueue.class) // exact match |
261 if (pq.getClass() == PriorityBlockingQueue.class) // exact match |
265 heapify = false; |
262 heapify = false; |
266 } |
263 } |
267 Object[] a = c.toArray(); |
264 Object[] es = c.toArray(); |
268 int n = a.length; |
265 int n = es.length; |
269 // If c.toArray incorrectly doesn't return Object[], copy it. |
266 // If c.toArray incorrectly doesn't return Object[], copy it. |
270 if (a.getClass() != Object[].class) |
267 if (es.getClass() != Object[].class) |
271 a = Arrays.copyOf(a, n, Object[].class); |
268 es = Arrays.copyOf(es, n, Object[].class); |
272 if (screen && (n == 1 || this.comparator != null)) { |
269 if (screen && (n == 1 || this.comparator != null)) { |
273 for (Object elt : a) |
270 for (Object e : es) |
274 if (elt == null) |
271 if (e == null) |
275 throw new NullPointerException(); |
272 throw new NullPointerException(); |
276 } |
273 } |
277 this.queue = a; |
274 this.queue = ensureNonEmpty(es); |
278 this.size = n; |
275 this.size = n; |
279 if (heapify) |
276 if (heapify) |
280 heapify(); |
277 heapify(); |
|
278 } |
|
279 |
|
280 /** Ensures that queue[0] exists, helping peek() and poll(). */ |
|
281 private static Object[] ensureNonEmpty(Object[] es) { |
|
282 return (es.length > 0) ? es : new Object[1]; |
281 } |
283 } |
282 |
284 |
283 /** |
285 /** |
284 * Tries to grow array to accommodate at least one more element |
286 * Tries to grow array to accommodate at least one more element |
285 * (but normally expand by about 50%), giving up (allowing retry) |
287 * (but normally expand by about 50%), giving up (allowing retry) |
321 |
323 |
322 /** |
324 /** |
323 * Mechanics for poll(). Call only while holding lock. |
325 * Mechanics for poll(). Call only while holding lock. |
324 */ |
326 */ |
325 private E dequeue() { |
327 private E dequeue() { |
326 int n = size - 1; |
328 // assert lock.isHeldByCurrentThread(); |
327 if (n < 0) |
329 final Object[] es; |
328 return null; |
330 final E result; |
329 else { |
331 |
330 Object[] array = queue; |
332 if ((result = (E) ((es = queue)[0])) != null) { |
331 E result = (E) array[0]; |
333 final int n; |
332 E x = (E) array[n]; |
334 final E x = (E) es[(n = --size)]; |
333 array[n] = null; |
335 es[n] = null; |
334 Comparator<? super E> cmp = comparator; |
336 if (n > 0) { |
335 if (cmp == null) |
337 final Comparator<? super E> cmp; |
336 siftDownComparable(0, x, array, n); |
338 if ((cmp = comparator) == null) |
337 else |
339 siftDownComparable(0, x, es, n); |
338 siftDownUsingComparator(0, x, array, n, cmp); |
340 else |
339 size = n; |
341 siftDownUsingComparator(0, x, es, n, cmp); |
340 return result; |
342 } |
341 } |
343 } |
|
344 return result; |
342 } |
345 } |
343 |
346 |
344 /** |
347 /** |
345 * Inserts item x at position k, maintaining heap invariant by |
348 * Inserts item x at position k, maintaining heap invariant by |
346 * promoting x up the tree until it is greater than or equal to |
349 * promoting x up the tree until it is greater than or equal to |
350 * Comparable and Comparator versions are separated into different |
353 * Comparable and Comparator versions are separated into different |
351 * methods that are otherwise identical. (Similarly for siftDown.) |
354 * methods that are otherwise identical. (Similarly for siftDown.) |
352 * |
355 * |
353 * @param k the position to fill |
356 * @param k the position to fill |
354 * @param x the item to insert |
357 * @param x the item to insert |
355 * @param array the heap array |
358 * @param es the heap array |
356 */ |
359 */ |
357 private static <T> void siftUpComparable(int k, T x, Object[] array) { |
360 private static <T> void siftUpComparable(int k, T x, Object[] es) { |
358 Comparable<? super T> key = (Comparable<? super T>) x; |
361 Comparable<? super T> key = (Comparable<? super T>) x; |
359 while (k > 0) { |
362 while (k > 0) { |
360 int parent = (k - 1) >>> 1; |
363 int parent = (k - 1) >>> 1; |
361 Object e = array[parent]; |
364 Object e = es[parent]; |
362 if (key.compareTo((T) e) >= 0) |
365 if (key.compareTo((T) e) >= 0) |
363 break; |
366 break; |
364 array[k] = e; |
367 es[k] = e; |
365 k = parent; |
368 k = parent; |
366 } |
369 } |
367 array[k] = key; |
370 es[k] = key; |
368 } |
371 } |
369 |
372 |
370 private static <T> void siftUpUsingComparator(int k, T x, Object[] array, |
373 private static <T> void siftUpUsingComparator( |
371 Comparator<? super T> cmp) { |
374 int k, T x, Object[] es, Comparator<? super T> cmp) { |
372 while (k > 0) { |
375 while (k > 0) { |
373 int parent = (k - 1) >>> 1; |
376 int parent = (k - 1) >>> 1; |
374 Object e = array[parent]; |
377 Object e = es[parent]; |
375 if (cmp.compare(x, (T) e) >= 0) |
378 if (cmp.compare(x, (T) e) >= 0) |
376 break; |
379 break; |
377 array[k] = e; |
380 es[k] = e; |
378 k = parent; |
381 k = parent; |
379 } |
382 } |
380 array[k] = x; |
383 es[k] = x; |
381 } |
384 } |
382 |
385 |
383 /** |
386 /** |
384 * Inserts item x at position k, maintaining heap invariant by |
387 * Inserts item x at position k, maintaining heap invariant by |
385 * demoting x down the tree repeatedly until it is less than or |
388 * demoting x down the tree repeatedly until it is less than or |
386 * equal to its children or is a leaf. |
389 * equal to its children or is a leaf. |
387 * |
390 * |
388 * @param k the position to fill |
391 * @param k the position to fill |
389 * @param x the item to insert |
392 * @param x the item to insert |
390 * @param array the heap array |
393 * @param es the heap array |
391 * @param n heap size |
394 * @param n heap size |
392 */ |
395 */ |
393 private static <T> void siftDownComparable(int k, T x, Object[] array, |
396 private static <T> void siftDownComparable(int k, T x, Object[] es, int n) { |
394 int n) { |
397 // assert n > 0; |
395 if (n > 0) { |
398 Comparable<? super T> key = (Comparable<? super T>)x; |
396 Comparable<? super T> key = (Comparable<? super T>)x; |
399 int half = n >>> 1; // loop while a non-leaf |
397 int half = n >>> 1; // loop while a non-leaf |
400 while (k < half) { |
398 while (k < half) { |
401 int child = (k << 1) + 1; // assume left child is least |
399 int child = (k << 1) + 1; // assume left child is least |
402 Object c = es[child]; |
400 Object c = array[child]; |
403 int right = child + 1; |
401 int right = child + 1; |
404 if (right < n && |
402 if (right < n && |
405 ((Comparable<? super T>) c).compareTo((T) es[right]) > 0) |
403 ((Comparable<? super T>) c).compareTo((T) array[right]) > 0) |
406 c = es[child = right]; |
404 c = array[child = right]; |
407 if (key.compareTo((T) c) <= 0) |
405 if (key.compareTo((T) c) <= 0) |
408 break; |
406 break; |
409 es[k] = c; |
407 array[k] = c; |
410 k = child; |
408 k = child; |
411 } |
409 } |
412 es[k] = key; |
410 array[k] = key; |
413 } |
411 } |
414 |
412 } |
415 private static <T> void siftDownUsingComparator( |
413 |
416 int k, T x, Object[] es, int n, Comparator<? super T> cmp) { |
414 private static <T> void siftDownUsingComparator(int k, T x, Object[] array, |
417 // assert n > 0; |
415 int n, |
418 int half = n >>> 1; |
416 Comparator<? super T> cmp) { |
419 while (k < half) { |
417 if (n > 0) { |
420 int child = (k << 1) + 1; |
418 int half = n >>> 1; |
421 Object c = es[child]; |
419 while (k < half) { |
422 int right = child + 1; |
420 int child = (k << 1) + 1; |
423 if (right < n && cmp.compare((T) c, (T) es[right]) > 0) |
421 Object c = array[child]; |
424 c = es[child = right]; |
422 int right = child + 1; |
425 if (cmp.compare(x, (T) c) <= 0) |
423 if (right < n && cmp.compare((T) c, (T) array[right]) > 0) |
426 break; |
424 c = array[child = right]; |
427 es[k] = c; |
425 if (cmp.compare(x, (T) c) <= 0) |
428 k = child; |
426 break; |
429 } |
427 array[k] = c; |
430 es[k] = x; |
428 k = child; |
|
429 } |
|
430 array[k] = x; |
|
431 } |
|
432 } |
431 } |
433 |
432 |
434 /** |
433 /** |
435 * Establishes the heap invariant (described above) in the entire tree, |
434 * Establishes the heap invariant (described above) in the entire tree, |
436 * assuming nothing about the order of the elements prior to the call. |
435 * assuming nothing about the order of the elements prior to the call. |
437 * This classic algorithm due to Floyd (1964) is known to be O(size). |
436 * This classic algorithm due to Floyd (1964) is known to be O(size). |
438 */ |
437 */ |
439 private void heapify() { |
438 private void heapify() { |
440 Object[] array = queue; |
439 final Object[] es = queue; |
441 int n = size, i = (n >>> 1) - 1; |
440 int n = size, i = (n >>> 1) - 1; |
442 Comparator<? super E> cmp = comparator; |
441 final Comparator<? super E> cmp; |
443 if (cmp == null) { |
442 if ((cmp = comparator) == null) |
444 for (; i >= 0; i--) |
443 for (; i >= 0; i--) |
445 siftDownComparable(i, (E) array[i], array, n); |
444 siftDownComparable(i, (E) es[i], es, n); |
446 } |
445 else |
447 else { |
|
448 for (; i >= 0; i--) |
446 for (; i >= 0; i--) |
449 siftDownUsingComparator(i, (E) array[i], array, n, cmp); |
447 siftDownUsingComparator(i, (E) es[i], es, n, cmp); |
450 } |
|
451 } |
448 } |
452 |
449 |
453 /** |
450 /** |
454 * Inserts the specified element into this priority queue. |
451 * Inserts the specified element into this priority queue. |
455 * |
452 * |
610 return Integer.MAX_VALUE; |
607 return Integer.MAX_VALUE; |
611 } |
608 } |
612 |
609 |
613 private int indexOf(Object o) { |
610 private int indexOf(Object o) { |
614 if (o != null) { |
611 if (o != null) { |
615 Object[] array = queue; |
612 final Object[] es = queue; |
616 int n = size; |
613 for (int i = 0, n = size; i < n; i++) |
617 for (int i = 0; i < n; i++) |
614 if (o.equals(es[i])) |
618 if (o.equals(array[i])) |
|
619 return i; |
615 return i; |
620 } |
616 } |
621 return -1; |
617 return -1; |
622 } |
618 } |
623 |
619 |
624 /** |
620 /** |
625 * Removes the ith element from queue. |
621 * Removes the ith element from queue. |
626 */ |
622 */ |
627 private void removeAt(int i) { |
623 private void removeAt(int i) { |
628 Object[] array = queue; |
624 final Object[] es = queue; |
629 int n = size - 1; |
625 final int n = size - 1; |
630 if (n == i) // removed last element |
626 if (n == i) // removed last element |
631 array[i] = null; |
627 es[i] = null; |
632 else { |
628 else { |
633 E moved = (E) array[n]; |
629 E moved = (E) es[n]; |
634 array[n] = null; |
630 es[n] = null; |
635 Comparator<? super E> cmp = comparator; |
631 final Comparator<? super E> cmp; |
636 if (cmp == null) |
632 if ((cmp = comparator) == null) |
637 siftDownComparable(i, moved, array, n); |
633 siftDownComparable(i, moved, es, n); |
638 else |
634 else |
639 siftDownUsingComparator(i, moved, array, n, cmp); |
635 siftDownUsingComparator(i, moved, es, n, cmp); |
640 if (array[i] == moved) { |
636 if (es[i] == moved) { |
641 if (cmp == null) |
637 if (cmp == null) |
642 siftUpComparable(i, moved, array); |
638 siftUpComparable(i, moved, es); |
643 else |
639 else |
644 siftUpUsingComparator(i, moved, array, cmp); |
640 siftUpUsingComparator(i, moved, es, cmp); |
645 } |
641 } |
646 } |
642 } |
647 size = n; |
643 size = n; |
648 } |
644 } |
649 |
645 |
1006 */ |
1015 */ |
1007 public Spliterator<E> spliterator() { |
1016 public Spliterator<E> spliterator() { |
1008 return new PBQSpliterator(); |
1017 return new PBQSpliterator(); |
1009 } |
1018 } |
1010 |
1019 |
|
1020 /** |
|
1021 * @throws NullPointerException {@inheritDoc} |
|
1022 */ |
|
1023 public boolean removeIf(Predicate<? super E> filter) { |
|
1024 Objects.requireNonNull(filter); |
|
1025 return bulkRemove(filter); |
|
1026 } |
|
1027 |
|
1028 /** |
|
1029 * @throws NullPointerException {@inheritDoc} |
|
1030 */ |
|
1031 public boolean removeAll(Collection<?> c) { |
|
1032 Objects.requireNonNull(c); |
|
1033 return bulkRemove(e -> c.contains(e)); |
|
1034 } |
|
1035 |
|
1036 /** |
|
1037 * @throws NullPointerException {@inheritDoc} |
|
1038 */ |
|
1039 public boolean retainAll(Collection<?> c) { |
|
1040 Objects.requireNonNull(c); |
|
1041 return bulkRemove(e -> !c.contains(e)); |
|
1042 } |
|
1043 |
|
1044 // A tiny bit set implementation |
|
1045 |
|
1046 private static long[] nBits(int n) { |
|
1047 return new long[((n - 1) >> 6) + 1]; |
|
1048 } |
|
1049 private static void setBit(long[] bits, int i) { |
|
1050 bits[i >> 6] |= 1L << i; |
|
1051 } |
|
1052 private static boolean isClear(long[] bits, int i) { |
|
1053 return (bits[i >> 6] & (1L << i)) == 0; |
|
1054 } |
|
1055 |
|
1056 /** Implementation of bulk remove methods. */ |
|
1057 private boolean bulkRemove(Predicate<? super E> filter) { |
|
1058 final ReentrantLock lock = this.lock; |
|
1059 lock.lock(); |
|
1060 try { |
|
1061 final Object[] es = queue; |
|
1062 final int end = size; |
|
1063 int i; |
|
1064 // Optimize for initial run of survivors |
|
1065 for (i = 0; i < end && !filter.test((E) es[i]); i++) |
|
1066 ; |
|
1067 if (i >= end) |
|
1068 return false; |
|
1069 // Tolerate predicates that reentrantly access the |
|
1070 // collection for read, so traverse once to find elements |
|
1071 // to delete, a second pass to physically expunge. |
|
1072 final int beg = i; |
|
1073 final long[] deathRow = nBits(end - beg); |
|
1074 deathRow[0] = 1L; // set bit 0 |
|
1075 for (i = beg + 1; i < end; i++) |
|
1076 if (filter.test((E) es[i])) |
|
1077 setBit(deathRow, i - beg); |
|
1078 int w = beg; |
|
1079 for (i = beg; i < end; i++) |
|
1080 if (isClear(deathRow, i - beg)) |
|
1081 es[w++] = es[i]; |
|
1082 for (i = size = w; i < end; i++) |
|
1083 es[i] = null; |
|
1084 heapify(); |
|
1085 return true; |
|
1086 } finally { |
|
1087 lock.unlock(); |
|
1088 } |
|
1089 } |
|
1090 |
|
1091 /** |
|
1092 * @throws NullPointerException {@inheritDoc} |
|
1093 */ |
|
1094 public void forEach(Consumer<? super E> action) { |
|
1095 Objects.requireNonNull(action); |
|
1096 final ReentrantLock lock = this.lock; |
|
1097 lock.lock(); |
|
1098 try { |
|
1099 final Object[] es = queue; |
|
1100 for (int i = 0, n = size; i < n; i++) |
|
1101 action.accept((E) es[i]); |
|
1102 } finally { |
|
1103 lock.unlock(); |
|
1104 } |
|
1105 } |
|
1106 |
1011 // VarHandle mechanics |
1107 // VarHandle mechanics |
1012 private static final VarHandle ALLOCATIONSPINLOCK; |
1108 private static final VarHandle ALLOCATIONSPINLOCK; |
1013 static { |
1109 static { |
1014 try { |
1110 try { |
1015 MethodHandles.Lookup l = MethodHandles.lookup(); |
1111 MethodHandles.Lookup l = MethodHandles.lookup(); |