--- jsr166/src/main/java/util/PriorityQueue.java 2018/05/06 21:07:41 1.125 +++ jsr166/src/main/java/util/PriorityQueue.java 2018/11/11 16:27:28 1.130 @@ -26,7 +26,8 @@ package java.util; import java.util.function.Consumer; -import jdk.internal.misc.SharedSecrets; +import java.util.function.Predicate; +// OPENJDK import jdk.internal.access.SharedSecrets; /** * An unbounded priority {@linkplain Queue queue} based on a priority heap. @@ -74,7 +75,7 @@ import jdk.internal.misc.SharedSecrets; * ({@code peek}, {@code element}, and {@code size}). * *

This class is a member of the - * + * * Java Collections Framework. * * @since 1.5 @@ -617,17 +618,18 @@ public class PriorityQueue extends Ab */ E removeAt(int i) { // assert i >= 0 && i < size; + final Object[] es = queue; modCount++; int s = --size; if (s == i) // removed last element - queue[i] = null; + es[i] = null; else { - E moved = (E) queue[s]; - queue[s] = null; + E moved = (E) es[s]; + es[s] = null; siftDown(i, moved); - if (queue[i] == moved) { + if (es[i] == moved) { siftUp(i, moved); - if (queue[i] != moved) + if (es[i] != moved) return moved; } } @@ -801,7 +803,7 @@ public class PriorityQueue extends Ab // Read in (and discard) array length s.readInt(); - SharedSecrets.getJavaObjectInputStreamAccess().checkArray(s, Object[].class, size); + jsr166.Platform.checkArray(s, Object[].class, size); final Object[] es = queue = new Object[Math.max(size, 1)]; // Read in all elements. @@ -900,6 +902,77 @@ public class PriorityQueue extends Ab } /** + * @throws NullPointerException {@inheritDoc} + */ + public boolean removeIf(Predicate filter) { + Objects.requireNonNull(filter); + return bulkRemove(filter); + } + + /** + * @throws NullPointerException {@inheritDoc} + */ + public boolean removeAll(Collection c) { + Objects.requireNonNull(c); + return bulkRemove(e -> c.contains(e)); + } + + /** + * @throws NullPointerException {@inheritDoc} + */ + public boolean retainAll(Collection c) { + Objects.requireNonNull(c); + return bulkRemove(e -> !c.contains(e)); + } + + // A tiny bit set implementation + + private static long[] nBits(int n) { + return new long[((n - 1) >> 6) + 1]; + } + private static void setBit(long[] bits, int i) { + bits[i >> 6] |= 1L << i; + } + private static boolean isClear(long[] bits, int i) { + return (bits[i >> 6] & (1L << i)) == 0; + } + + /** Implementation of bulk remove methods. */ + private boolean bulkRemove(Predicate filter) { + final int expectedModCount = ++modCount; + final Object[] es = queue; + final int end = size; + int i; + // Optimize for initial run of survivors + for (i = 0; i < end && !filter.test((E) es[i]); i++) + ; + if (i >= end) { + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + return false; + } + // Tolerate predicates that reentrantly access the collection for + // read (but writers still get CME), so traverse once to find + // elements to delete, a second pass to physically expunge. + final int beg = i; + final long[] deathRow = nBits(end - beg); + deathRow[0] = 1L; // set bit 0 + for (i = beg + 1; i < end; i++) + if (filter.test((E) es[i])) + setBit(deathRow, i - beg); + if (modCount != expectedModCount) + throw new ConcurrentModificationException(); + int w = beg; + for (i = beg; i < end; i++) + if (isClear(deathRow, i - beg)) + es[w++] = es[i]; + for (i = size = w; i < end; i++) + es[i] = null; + heapify(); + return true; + } + + /** * @throws NullPointerException {@inheritDoc} */ public void forEach(Consumer action) {