
soot.util.PriorityQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot Show documentation
Show all versions of soot Show documentation
A Java Optimization Framework
/**
*
*/
package soot.util;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 1997 - 2018 Raja Vallée-Rai and others
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.util.AbstractMap;
import java.util.AbstractQueue;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A fixed size priority queue based on bitsets. The elements of the priority queue are ordered according to a given
* universe. This priority queue does not permit {@code null} elements. Inserting of elements that are not part of the
* universe is also permitted (doing so will result in a {@code NoSuchElementException}).
*
* @author Steven Lambeth
* @param
* the type of elements held in the universe
*/
abstract public class PriorityQueue extends AbstractQueue {
private static final Logger logger = LoggerFactory.getLogger(PriorityQueue.class);
abstract class Itr implements Iterator {
long expected = getExpected();
int next = min;
int now = Integer.MAX_VALUE;
abstract long getExpected();
@Override
public boolean hasNext() {
return next < N;
}
@Override
public E next() {
if (expected != getExpected()) {
throw new ConcurrentModificationException();
}
if (next >= N) {
throw new NoSuchElementException();
}
now = next;
next = nextSetBit(next + 1);
return universe.get(now);
}
@Override
public void remove() {
if (now >= N) {
throw new IllegalStateException();
}
if (expected != getExpected()) {
throw new ConcurrentModificationException();
}
PriorityQueue.this.remove(now);
expected = getExpected();
now = Integer.MAX_VALUE;
}
}
final List extends E> universe;
final int N;
int min = Integer.MAX_VALUE;
private Map ordinalMap;
int getOrdinal(Object o) {
if (o == null) {
throw new NullPointerException();
}
Integer i = ordinalMap.get(o);
if (i == null) {
throw new NoSuchElementException();
}
return i.intValue();
}
/**
* Adds all elements of the universe to this queue.
*/
abstract void addAll();
/**
* Returns the index of the first bit that is set to true
that occurs on or after the specified starting
* index. If no such bit exists then a value bigger that {@code N} is returned.
*
* @param fromIndex
* the index to start checking from (inclusive).
* @return the index of the next set bit.
*/
abstract int nextSetBit(int fromIndex);
abstract boolean remove(int ordinal);
abstract boolean add(int ordinal);
abstract boolean contains(int ordinal);
/**
* {@inheritDoc}
*
*/
@Override
final public E peek() {
return isEmpty() ? null : universe.get(min);
}
/**
* {@inheritDoc}
*
*/
@Override
final public E poll() {
if (isEmpty()) {
return null;
}
E e = universe.get(min);
remove(min);
return e;
}
/**
* {@inheritDoc}
*
* @throws NoSuchElementException
* if e not part of the universe
* @throws NullPointerException
* if e is {@code null}
*/
@Override
final public boolean add(E e) {
return offer(e);
}
/**
* {@inheritDoc}
*
* @throws NoSuchElementException
* if e not part of the universe
* @throws NullPointerException
* if e is {@code null}
*/
@Override
final public boolean offer(E e) {
return add(getOrdinal(e));
}
/**
* {@inheritDoc}
*
*/
@Override
final public boolean remove(Object o) {
if (o == null || isEmpty()) {
return false;
}
try {
if (o.equals(peek())) {
remove(min);
return true;
}
return remove(getOrdinal(o));
} catch (NoSuchElementException e) {
logger.debug("" + e.getMessage());
}
return false;
}
/**
* {@inheritDoc}
*
*/
@Override
final public boolean contains(Object o) {
if (o == null) {
return false;
}
try {
if (o.equals(peek())) {
return true;
}
return contains(getOrdinal(o));
} catch (NoSuchElementException e) {
logger.debug("" + e.getMessage());
}
return false;
}
/**
* {@inheritDoc}
*
*/
@Override
public boolean isEmpty() {
return min >= N;
}
PriorityQueue(List extends E> universe, Map ordinalMap) {
assert ordinalMap.size() == universe.size();
this.universe = universe;
this.ordinalMap = ordinalMap;
this.N = universe.size();
}
/**
* Creates a new full priority queue
*
* @param universe
* @return
*/
public static PriorityQueue of(E[] universe) {
return of(Arrays.asList(universe));
}
/**
* Creates a new empty priority queue
*
* @param universe
* @return
*/
public static PriorityQueue noneOf(E[] universe) {
return noneOf(Arrays.asList(universe));
}
/**
* Creates a new full priority queue
*
* @param universe
* @return
*/
public static PriorityQueue of(List extends E> universe) {
PriorityQueue q = noneOf(universe);
q.addAll();
return q;
}
/**
* Creates a new empty priority queue
*
* @param universe
* @return
*/
public static PriorityQueue noneOf(List extends E> universe) {
Map ordinalMap = new HashMap(2 * universe.size() / 3);
int i = 0;
for (E e : universe) {
if (e == null) {
throw new NullPointerException("null is not allowed");
}
if (ordinalMap.put(e, i++) != null) {
throw new IllegalArgumentException("duplicate key found");
}
}
return newPriorityQueue(universe, ordinalMap);
}
public static PriorityQueue of(List extends E> universe, boolean useNumberInterface) {
PriorityQueue q = noneOf(universe, useNumberInterface);
q.addAll();
return q;
}
public static PriorityQueue noneOf(final List extends E> universe,
boolean useNumberInterface) {
if (!useNumberInterface) {
return noneOf(universe);
}
int i = 0;
for (E e : universe) {
e.setNumber(i++);
}
return newPriorityQueue(universe, new AbstractMap() {
@SuppressWarnings("unchecked")
@Override
public Integer get(Object key) {
return ((E) key).getNumber();
}
@Override
public int size() {
return universe.size();
}
@Override
public Set> entrySet() {
throw new UnsupportedOperationException();
}
});
}
private static PriorityQueue newPriorityQueue(List extends E> universe, Map ordinalMap) {
if (universe.size() <= SmallPriorityQueue.MAX_CAPACITY) {
return new SmallPriorityQueue(universe, ordinalMap);
}
if (universe.size() <= MediumPriorityQueue.MAX_CAPACITY) {
return new MediumPriorityQueue(universe, ordinalMap);
}
return new LargePriorityQueue(universe, ordinalMap);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy