ARTEMIS-3373 Using consistent template terminology under the collections package
This commit is contained in:
parent
200e436931
commit
4d7c6cc188
|
@ -22,9 +22,9 @@ import java.util.Collection;
|
||||||
* Provides an Array Iterator that is able to reset, allowing you to iterate over the full array.
|
* Provides an Array Iterator that is able to reset, allowing you to iterate over the full array.
|
||||||
* It achieves this though by moving end position mark to the the current cursors position,
|
* It achieves this though by moving end position mark to the the current cursors position,
|
||||||
* so it round robins, even with reset.
|
* so it round robins, even with reset.
|
||||||
* @param <T>
|
* @param <E>
|
||||||
*/
|
*/
|
||||||
public class ArrayResettableIterator<T> implements ResettableIterator<T> {
|
public class ArrayResettableIterator<E> implements ResettableIterator<E> {
|
||||||
|
|
||||||
private final Object[] array;
|
private final Object[] array;
|
||||||
private int cursor = 0;
|
private int cursor = 0;
|
||||||
|
@ -36,7 +36,7 @@ public class ArrayResettableIterator<T> implements ResettableIterator<T> {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> ResettableIterator<T> iterator(Collection<T> collection) {
|
public static <E> ResettableIterator<E> iterator(Collection<E> collection) {
|
||||||
return new ArrayResettableIterator<>(collection.toArray());
|
return new ArrayResettableIterator<>(collection.toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,11 +52,12 @@ public class ArrayResettableIterator<T> implements ResettableIterator<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T next() {
|
public E next() {
|
||||||
if (!hasNext) {
|
if (!hasNext) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
@SuppressWarnings("unchecked") T result = (T) array[cursor];
|
@SuppressWarnings("unchecked")
|
||||||
|
E result = (E) array[cursor];
|
||||||
cursor++;
|
cursor++;
|
||||||
if (cursor == array.length) {
|
if (cursor == array.length) {
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
|
|
|
@ -25,15 +25,15 @@ import java.util.function.IntFunction;
|
||||||
* This collection is a concurrent append-only list that grows in chunks.<br>
|
* This collection is a concurrent append-only list that grows in chunks.<br>
|
||||||
* It's safe to be used by many threads concurrently and has a max capacity of {@link Integer#MAX_VALUE}.
|
* It's safe to be used by many threads concurrently and has a max capacity of {@link Integer#MAX_VALUE}.
|
||||||
*/
|
*/
|
||||||
public final class ConcurrentAppendOnlyChunkedList<T> {
|
public final class ConcurrentAppendOnlyChunkedList<E> {
|
||||||
|
|
||||||
private static final class AtomicChunk<T> extends AtomicReferenceArray<T> {
|
private static final class AtomicChunk<E> extends AtomicReferenceArray<E> {
|
||||||
|
|
||||||
AtomicChunk<T> next = null;
|
AtomicChunk<E> next = null;
|
||||||
final AtomicChunk<T> prev;
|
final AtomicChunk<E> prev;
|
||||||
final int index;
|
final int index;
|
||||||
|
|
||||||
AtomicChunk(int index, AtomicChunk<T> prev, int length) {
|
AtomicChunk(int index, AtomicChunk<E> prev, int length) {
|
||||||
super(length);
|
super(length);
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.prev = prev;
|
this.prev = prev;
|
||||||
|
@ -48,9 +48,9 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
|
|
||||||
private final int chunkSizeLog2;
|
private final int chunkSizeLog2;
|
||||||
|
|
||||||
private AtomicChunk<T> firstBuffer = null;
|
private AtomicChunk<E> firstBuffer = null;
|
||||||
|
|
||||||
private AtomicChunk<T> lastBuffer = null;
|
private AtomicChunk<E> lastBuffer = null;
|
||||||
|
|
||||||
//it is both the current index of the next element to be claimed and the current size of the collection
|
//it is both the current index of the next element to be claimed and the current size of the collection
|
||||||
//it's using a parity bit to mark the rotation state ie size === lastIndex >> 1
|
//it's using a parity bit to mark the rotation state ie size === lastIndex >> 1
|
||||||
|
@ -86,8 +86,8 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
/**
|
/**
|
||||||
* It appends {@code elements} to the collection.
|
* It appends {@code elements} to the collection.
|
||||||
*/
|
*/
|
||||||
public void addAll(T[] elements) {
|
public void addAll(E[] elements) {
|
||||||
for (T e : elements) {
|
for (E e : elements) {
|
||||||
add(e);
|
add(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
/**
|
/**
|
||||||
* Returns the element at the specified position in this collection or {@code null} if not found.
|
* Returns the element at the specified position in this collection or {@code null} if not found.
|
||||||
*/
|
*/
|
||||||
public T get(int index) {
|
public E get(int index) {
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
if (index >= lastIndex) {
|
if (index >= lastIndex) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final AtomicChunk<T> buffer;
|
final AtomicChunk<E> buffer;
|
||||||
final int offset;
|
final int offset;
|
||||||
if (index >= chunkSize) {
|
if (index >= chunkSize) {
|
||||||
offset = index & chunkMask;
|
offset = index & chunkMask;
|
||||||
|
@ -121,20 +121,20 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
* Implements a lock-free version of the optimization used on {@link java.util.LinkedList#get(int)} to speed up queries
|
* Implements a lock-free version of the optimization used on {@link java.util.LinkedList#get(int)} to speed up queries
|
||||||
* ie backward search of a node if needed.
|
* ie backward search of a node if needed.
|
||||||
*/
|
*/
|
||||||
private AtomicChunk<T> getChunkOf(final int index, final long lastIndex) {
|
private AtomicChunk<E> getChunkOf(final int index, final long lastIndex) {
|
||||||
final int chunkSizeLog2 = this.chunkSizeLog2;
|
final int chunkSizeLog2 = this.chunkSizeLog2;
|
||||||
//fast division by a power of 2
|
//fast division by a power of 2
|
||||||
final int chunkIndex = index >> chunkSizeLog2;
|
final int chunkIndex = index >> chunkSizeLog2;
|
||||||
//size is never allowed to be > Integer.MAX_VALUE
|
//size is never allowed to be > Integer.MAX_VALUE
|
||||||
final int lastChunkIndex = (int) lastIndex >> chunkSizeLog2;
|
final int lastChunkIndex = (int) lastIndex >> chunkSizeLog2;
|
||||||
int distance = chunkIndex;
|
int distance = chunkIndex;
|
||||||
AtomicChunk<T> buffer = null;
|
AtomicChunk<E> buffer = null;
|
||||||
boolean forward = true;
|
boolean forward = true;
|
||||||
int distanceFromLast = lastChunkIndex - chunkIndex;
|
int distanceFromLast = lastChunkIndex - chunkIndex;
|
||||||
//it's worth to go backward from lastChunkIndex?
|
//it's worth to go backward from lastChunkIndex?
|
||||||
//trying first to check against the value we already have: if it won't worth, won't make sense to load the lastBuffer
|
//trying first to check against the value we already have: if it won't worth, won't make sense to load the lastBuffer
|
||||||
if (distanceFromLast < distance) {
|
if (distanceFromLast < distance) {
|
||||||
final AtomicChunk<T> lastBuffer = this.lastBuffer;
|
final AtomicChunk<E> lastBuffer = this.lastBuffer;
|
||||||
//lastBuffer is a potential moving, always increasing, target ie better to re-check the distance
|
//lastBuffer is a potential moving, always increasing, target ie better to re-check the distance
|
||||||
distanceFromLast = lastBuffer.index - chunkIndex;
|
distanceFromLast = lastBuffer.index - chunkIndex;
|
||||||
if (distanceFromLast < distance) {
|
if (distanceFromLast < distance) {
|
||||||
|
@ -161,7 +161,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
*
|
*
|
||||||
* @throws NullPointerException if {@code e} is {@code null}
|
* @throws NullPointerException if {@code e} is {@code null}
|
||||||
**/
|
**/
|
||||||
public void add(T e) {
|
public void add(E e) {
|
||||||
Objects.requireNonNull(e);
|
Objects.requireNonNull(e);
|
||||||
while (true) {
|
while (true) {
|
||||||
final long lastIndex = this.lastIndex;
|
final long lastIndex = this.lastIndex;
|
||||||
|
@ -174,7 +174,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
throw new IllegalStateException("can't add more then " + Integer.MAX_VALUE + " elements");
|
throw new IllegalStateException("can't add more then " + Integer.MAX_VALUE + " elements");
|
||||||
}
|
}
|
||||||
//load acquire the current lastBuffer
|
//load acquire the current lastBuffer
|
||||||
final AtomicChunk<T> lastBuffer = this.lastBuffer;
|
final AtomicChunk<E> lastBuffer = this.lastBuffer;
|
||||||
final int offset = (int) (validLastIndex & chunkMask);
|
final int offset = (int) (validLastIndex & chunkMask);
|
||||||
//only the first attempt to add an element to a chunk can attempt to resize
|
//only the first attempt to add an element to a chunk can attempt to resize
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
|
@ -190,12 +190,12 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addChunkAndElement(AtomicChunk<T> lastBuffer, long lastIndex, long validLastIndex, T element) {
|
private boolean addChunkAndElement(AtomicChunk<E> lastBuffer, long lastIndex, long validLastIndex, E element) {
|
||||||
// adding 1 will set the lower bit
|
// adding 1 will set the lower bit
|
||||||
if (!LAST_INDEX_UPDATER.compareAndSet(this, lastIndex, lastIndex + 1)) {
|
if (!LAST_INDEX_UPDATER.compareAndSet(this, lastIndex, lastIndex + 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final AtomicChunk<T> newChunk;
|
final AtomicChunk<E> newChunk;
|
||||||
try {
|
try {
|
||||||
final int index = (int) (validLastIndex >> chunkSizeLog2);
|
final int index = (int) (validLastIndex >> chunkSizeLog2);
|
||||||
newChunk = new AtomicChunk<>(index, lastBuffer, chunkSize);
|
newChunk = new AtomicChunk<>(index, lastBuffer, chunkSize);
|
||||||
|
@ -222,7 +222,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T[] toArray(IntFunction<T[]> arrayAllocator) {
|
public E[] toArray(IntFunction<E[]> arrayAllocator) {
|
||||||
return toArray(arrayAllocator, 0);
|
return toArray(arrayAllocator, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,21 +231,21 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
* sequence (from first to last element).<br>
|
* sequence (from first to last element).<br>
|
||||||
* {@code arrayAllocator} will be used to instantiate the array of the correct size with the right runtime type.
|
* {@code arrayAllocator} will be used to instantiate the array of the correct size with the right runtime type.
|
||||||
*/
|
*/
|
||||||
public T[] toArray(IntFunction<T[]> arrayAllocator, int startIndex) {
|
public E[] toArray(IntFunction<E[]> arrayAllocator, int startIndex) {
|
||||||
if (startIndex < 0) {
|
if (startIndex < 0) {
|
||||||
throw new ArrayIndexOutOfBoundsException("startIndex must be >= 0");
|
throw new ArrayIndexOutOfBoundsException("startIndex must be >= 0");
|
||||||
}
|
}
|
||||||
final long lastIndex = getValidLastIndex();
|
final long lastIndex = getValidLastIndex();
|
||||||
assert lastIndex <= Integer.MAX_VALUE;
|
assert lastIndex <= Integer.MAX_VALUE;
|
||||||
final int size = (int) lastIndex;
|
final int size = (int) lastIndex;
|
||||||
final T[] elements = arrayAllocator.apply(size);
|
final E[] elements = arrayAllocator.apply(size);
|
||||||
if (startIndex + size > elements.length) {
|
if (startIndex + size > elements.length) {
|
||||||
throw new ArrayIndexOutOfBoundsException();
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
//fast division by a power of 2
|
//fast division by a power of 2
|
||||||
final int chunkSize = this.chunkSize;
|
final int chunkSize = this.chunkSize;
|
||||||
final int chunks = size > chunkSize ? size >> chunkSizeLog2 : 0;
|
final int chunks = size > chunkSize ? size >> chunkSizeLog2 : 0;
|
||||||
AtomicChunk<T> buffer = firstBuffer;
|
AtomicChunk<E> buffer = firstBuffer;
|
||||||
int elementIndex = startIndex;
|
int elementIndex = startIndex;
|
||||||
for (int i = 0; i < chunks; i++) {
|
for (int i = 0; i < chunks; i++) {
|
||||||
drain(buffer, elements, elementIndex, chunkSize);
|
drain(buffer, elements, elementIndex, chunkSize);
|
||||||
|
@ -259,16 +259,16 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: lastIndex is being updated BEFORE setting a new value ie on reader side need to spin until a not null value is set
|
//NOTE: lastIndex is being updated BEFORE setting a new value ie on reader side need to spin until a not null value is set
|
||||||
private static <T> T pollElement(AtomicChunk<T> buffer, int i) {
|
private static <E> E pollElement(AtomicChunk<E> buffer, int i) {
|
||||||
T e;
|
E e;
|
||||||
while ((e = buffer.get(i)) == null) {
|
while ((e = buffer.get(i)) == null) {
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> void drain(AtomicChunk<T> buffer, T[] elements, int elementNumber, int length) {
|
private static <E> void drain(AtomicChunk<E> buffer, E[] elements, int elementNumber, int length) {
|
||||||
for (int j = 0; j < length; j++) {
|
for (int j = 0; j < length; j++) {
|
||||||
final T e = pollElement(buffer, j);
|
final E e = pollElement(buffer, j);
|
||||||
assert e != null;
|
assert e != null;
|
||||||
elements[elementNumber] = e;
|
elements[elementNumber] = e;
|
||||||
elementNumber++;
|
elementNumber++;
|
||||||
|
|
|
@ -24,7 +24,7 @@ public final class IterableStream {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Iterable<T> iterableOf(Stream<T> stream) {
|
public static <E> Iterable<E> iterableOf(Stream<E> stream) {
|
||||||
return stream::iterator;
|
return stream::iterator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -372,30 +372,30 @@ public class LinkedListImpl<E> implements LinkedList<E> {
|
||||||
throw new IllegalStateException("Cannot find iter to remove");
|
throw new IllegalStateException("Cannot find iter to remove");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class NodeHolder<T> extends Node<T> {
|
private static final class NodeHolder<E> extends Node<E> {
|
||||||
|
|
||||||
private final T val;
|
private final E val;
|
||||||
|
|
||||||
//only the head is allowed to hold a null
|
//only the head is allowed to hold a null
|
||||||
private NodeHolder(T e) {
|
private NodeHolder(E e) {
|
||||||
val = e;
|
val = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected T val() {
|
protected E val() {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Node<T> {
|
public static class Node<E> {
|
||||||
|
|
||||||
private Node<T> next;
|
private Node<E> next;
|
||||||
|
|
||||||
private Node<T> prev;
|
private Node<E> prev;
|
||||||
|
|
||||||
private int iterCount;
|
private int iterCount;
|
||||||
|
|
||||||
private static <T> Node<T> with(final T o) {
|
private static <E> Node<E> with(final E o) {
|
||||||
Objects.requireNonNull(o, "Only HEAD nodes are allowed to hold null values");
|
Objects.requireNonNull(o, "Only HEAD nodes are allowed to hold null values");
|
||||||
if (o instanceof Node) {
|
if (o instanceof Node) {
|
||||||
final Node node = (Node) o;
|
final Node node = (Node) o;
|
||||||
|
@ -410,15 +410,15 @@ public class LinkedListImpl<E> implements LinkedList<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected T val() {
|
protected E val() {
|
||||||
return (T) this;
|
return (E) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final LinkedListImpl.Node<T> next() {
|
protected final LinkedListImpl.Node<E> next() {
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final LinkedListImpl.Node<T> prev() {
|
protected final LinkedListImpl.Node<E> prev() {
|
||||||
return prev;
|
return prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -405,14 +405,14 @@ public class LongHashSet extends AbstractSet<Long> implements Serializable {
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T> T[] toArray(final T[] a) {
|
public <E> E[] toArray(final E[] a) {
|
||||||
final Class<?> componentType = a.getClass().getComponentType();
|
final Class<?> componentType = a.getClass().getComponentType();
|
||||||
if (!componentType.isAssignableFrom(Long.class)) {
|
if (!componentType.isAssignableFrom(Long.class)) {
|
||||||
throw new ArrayStoreException("cannot store Longs in array of type " + componentType);
|
throw new ArrayStoreException("cannot store Longs in array of type " + componentType);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int size = size();
|
final int size = size();
|
||||||
final T[] arrayCopy = a.length >= size ? a : (T[]) Array.newInstance(componentType, size);
|
final E[] arrayCopy = a.length >= size ? a : (E[]) Array.newInstance(componentType, size);
|
||||||
copyValues(arrayCopy);
|
copyValues(arrayCopy);
|
||||||
|
|
||||||
return arrayCopy;
|
return arrayCopy;
|
||||||
|
|
|
@ -21,11 +21,11 @@ import java.util.Iterator;
|
||||||
/**
|
/**
|
||||||
* Provides an Iterator that works over multiple underlying iterators.
|
* Provides an Iterator that works over multiple underlying iterators.
|
||||||
*
|
*
|
||||||
* @param <T> type of the class of the iterator.
|
* @param <E> type of the class of the iterator.
|
||||||
*/
|
*/
|
||||||
public class MultiIterator<T> extends MultiIteratorBase<T, Iterator<T>> {
|
public class MultiIterator<E> extends MultiIteratorBase<E, Iterator<E>> {
|
||||||
|
|
||||||
public MultiIterator(Iterator<T>[] iterators) {
|
public MultiIterator(Iterator<E>[] iterators) {
|
||||||
super(iterators);
|
super(iterators);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,10 @@ import java.util.Iterator;
|
||||||
/**
|
/**
|
||||||
* Provides an Abstract Iterator that works over multiple underlying iterators.
|
* Provides an Abstract Iterator that works over multiple underlying iterators.
|
||||||
*
|
*
|
||||||
* @param <T> type of the class of the iterator.
|
* @param <E> type of the class of the iterator.
|
||||||
* @param <I> type of the iterator
|
* @param <I> type of the iterator
|
||||||
*/
|
*/
|
||||||
abstract class MultiIteratorBase<T, I extends Iterator<T>> implements Iterator<T> {
|
abstract class MultiIteratorBase<E, I extends Iterator<E>> implements Iterator<E> {
|
||||||
|
|
||||||
private final I[] iterators;
|
private final I[] iterators;
|
||||||
private int index = -1;
|
private int index = -1;
|
||||||
|
@ -52,7 +52,7 @@ abstract class MultiIteratorBase<T, I extends Iterator<T>> implements Iterator<T
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T next() {
|
public E next() {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
I currentIterator = get(index);
|
I currentIterator = get(index);
|
||||||
|
|
|
@ -20,11 +20,11 @@ package org.apache.activemq.artemis.utils.collections;
|
||||||
* Extends MultiIterator, adding the ability if the underlying iterators are resettable, then its self can reset.
|
* Extends MultiIterator, adding the ability if the underlying iterators are resettable, then its self can reset.
|
||||||
* It achieves this by going back to the first iterator, and as moves to another iterator it resets it.
|
* It achieves this by going back to the first iterator, and as moves to another iterator it resets it.
|
||||||
*
|
*
|
||||||
* @param <T> type of the class of the iterator.
|
* @param <E> type of the class of the iterator.
|
||||||
*/
|
*/
|
||||||
public class MultiResettableIterator<T> extends MultiIteratorBase<T, ResettableIterator<T>> implements ResettableIterator<T> {
|
public class MultiResettableIterator<E> extends MultiIteratorBase<E, ResettableIterator<E>> implements ResettableIterator<E> {
|
||||||
|
|
||||||
public MultiResettableIterator(ResettableIterator<T>[] iterators) {
|
public MultiResettableIterator(ResettableIterator<E>[] iterators) {
|
||||||
super(iterators);
|
super(iterators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,30 +38,30 @@ import java.util.stream.Collectors;
|
||||||
*
|
*
|
||||||
* Methods getArray, setArray MUST never be exposed, and all array modifications must go through these.
|
* Methods getArray, setArray MUST never be exposed, and all array modifications must go through these.
|
||||||
*
|
*
|
||||||
* @param <T> The type this class may hold, this is generic as can be anything that extends PriorityAware.
|
* @param <E> The type this class may hold, this is generic as can be anything that extends PriorityAware.
|
||||||
*/
|
*/
|
||||||
public class PriorityCollection<T extends PriorityAware> extends AbstractCollection<T> {
|
public class PriorityCollection<E extends PriorityAware> extends AbstractCollection<E> {
|
||||||
|
|
||||||
private final Supplier<Collection<T>> supplier;
|
private final Supplier<Collection<E>> supplier;
|
||||||
private volatile PriorityHolder<T>[] priorityHolders = newPrioritySetArrayInstance(0);
|
private volatile PriorityHolder<E>[] priorityHolders = newPrioritySetArrayInstance(0);
|
||||||
private volatile int size;
|
private volatile int size;
|
||||||
|
|
||||||
private void setArray(PriorityHolder<T>[] priorityHolders) {
|
private void setArray(PriorityHolder<E>[] priorityHolders) {
|
||||||
this.priorityHolders = priorityHolders;
|
this.priorityHolders = priorityHolders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PriorityHolder<T>[] getArray() {
|
private PriorityHolder<E>[] getArray() {
|
||||||
return priorityHolders;
|
return priorityHolders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public PriorityCollection(Supplier<Collection<T>> supplier) {
|
public PriorityCollection(Supplier<Collection<E>> supplier) {
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <T> PriorityHolder<T>[] newPrioritySetArrayInstance(int length) {
|
private static <E> PriorityHolder<E>[] newPrioritySetArrayInstance(int length) {
|
||||||
return (PriorityHolder<T>[]) Array.newInstance(PriorityHolder.class, length);
|
return (PriorityHolder<E>[]) Array.newInstance(PriorityHolder.class, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -75,20 +75,20 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getPriorites() {
|
public Set<Integer> getPriorites() {
|
||||||
PriorityHolder<T>[] snapshot = getArray();
|
PriorityHolder<E>[] snapshot = getArray();
|
||||||
return Arrays.stream(snapshot).map(PriorityAware::getPriority).collect(Collectors.toSet());
|
return Arrays.stream(snapshot).map(PriorityAware::getPriority).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterator<T> iterator() {
|
public Iterator<E> iterator() {
|
||||||
Iterator<T>[] iterators = getIterators();
|
Iterator<E>[] iterators = getIterators();
|
||||||
return new MultiIterator<>(iterators);
|
return new MultiIterator<>(iterators);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterator<T>[] getIterators() {
|
private Iterator<E>[] getIterators() {
|
||||||
PriorityHolder<T>[] snapshot = this.getArray();
|
PriorityHolder<E>[] snapshot = this.getArray();
|
||||||
int size = snapshot.length;
|
int size = snapshot.length;
|
||||||
Iterator<T>[] iterators = newIteratorArrayInstance(size);
|
Iterator<E>[] iterators = newIteratorArrayInstance(size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
iterators[i] = snapshot[i].getValues().iterator();
|
iterators[i] = snapshot[i].getValues().iterator();
|
||||||
}
|
}
|
||||||
|
@ -96,18 +96,18 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <T> Iterator<T>[] newIteratorArrayInstance(int length) {
|
private static <E> Iterator<E>[] newIteratorArrayInstance(int length) {
|
||||||
return (Iterator<T>[]) Array.newInstance(Iterator.class, length);
|
return (Iterator<E>[]) Array.newInstance(Iterator.class, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ResettableIterator<T> resettableIterator() {
|
public ResettableIterator<E> resettableIterator() {
|
||||||
return new MultiResettableIterator<T>(getResettableIterators());
|
return new MultiResettableIterator<E>(getResettableIterators());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResettableIterator<T>[] getResettableIterators() {
|
private ResettableIterator<E>[] getResettableIterators() {
|
||||||
PriorityHolder<T>[] snapshot = this.getArray();
|
PriorityHolder<E>[] snapshot = this.getArray();
|
||||||
int size = snapshot.length;
|
int size = snapshot.length;
|
||||||
ResettableIterator<T>[] iterators = newResettableIteratorArrayInstance(size);
|
ResettableIterator<E>[] iterators = newResettableIteratorArrayInstance(size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
iterators[i] = ArrayResettableIterator.iterator(snapshot[i].getValues());
|
iterators[i] = ArrayResettableIterator.iterator(snapshot[i].getValues());
|
||||||
}
|
}
|
||||||
|
@ -115,28 +115,28 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static <T> ResettableIterator<T>[] newResettableIteratorArrayInstance(int length) {
|
private static <E> ResettableIterator<E>[] newResettableIteratorArrayInstance(int length) {
|
||||||
return (ResettableIterator<T>[]) Array.newInstance(ResettableIterator.class, length);
|
return (ResettableIterator<E>[]) Array.newInstance(ResettableIterator.class, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void forEach(Consumer<? super T> action) {
|
public void forEach(Consumer<? super E> action) {
|
||||||
Objects.requireNonNull(action);
|
Objects.requireNonNull(action);
|
||||||
PriorityHolder<T>[] current = getArray();
|
PriorityHolder<E>[] current = getArray();
|
||||||
int len = current.length;
|
int len = current.length;
|
||||||
for (int i = 0; i < len; ++i) {
|
for (int i = 0; i < len; ++i) {
|
||||||
current[i].getValues().forEach(action);
|
current[i].getValues().forEach(action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<T> getCollection(int priority, boolean createIfMissing) {
|
private Collection<E> getCollection(int priority, boolean createIfMissing) {
|
||||||
PriorityHolder<T>[] current = getArray();
|
PriorityHolder<E>[] current = getArray();
|
||||||
int low = 0;
|
int low = 0;
|
||||||
int high = current.length - 1;
|
int high = current.length - 1;
|
||||||
|
|
||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
int mid = (low + high) >>> 1;
|
int mid = (low + high) >>> 1;
|
||||||
PriorityHolder<T> midVal = current[mid];
|
PriorityHolder<E> midVal = current[mid];
|
||||||
|
|
||||||
if (midVal.getPriority() > priority)
|
if (midVal.getPriority() > priority)
|
||||||
low = mid + 1;
|
low = mid + 1;
|
||||||
|
@ -147,14 +147,14 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createIfMissing) {
|
if (createIfMissing) {
|
||||||
PriorityHolder<T>[] newArray = newPrioritySetArrayInstance(current.length + 1);
|
PriorityHolder<E>[] newArray = newPrioritySetArrayInstance(current.length + 1);
|
||||||
if (low > 0) {
|
if (low > 0) {
|
||||||
System.arraycopy(current, 0, newArray, 0, low);
|
System.arraycopy(current, 0, newArray, 0, low);
|
||||||
}
|
}
|
||||||
if (current.length - low > 0) {
|
if (current.length - low > 0) {
|
||||||
System.arraycopy(current, low, newArray, low + 1, current.length - low);
|
System.arraycopy(current, low, newArray, low + 1, current.length - low);
|
||||||
}
|
}
|
||||||
newArray[low] = new PriorityHolder<T>(priority, supplier);
|
newArray[low] = new PriorityHolder<E>(priority, supplier);
|
||||||
setArray(newArray);
|
setArray(newArray);
|
||||||
return newArray[low].getValues();
|
return newArray[low].getValues();
|
||||||
}
|
}
|
||||||
|
@ -162,17 +162,17 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean add(T t) {
|
public synchronized boolean add(E e) {
|
||||||
if (size() == Integer.MAX_VALUE) return false;
|
if (size() == Integer.MAX_VALUE) return false;
|
||||||
boolean result = addInternal(t);
|
boolean result = addInternal(e);
|
||||||
calcSize();
|
calcSize();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addInternal(T t) {
|
private boolean addInternal(E e) {
|
||||||
if (t == null) return false;
|
if (e == null) return false;
|
||||||
Collection<T> priority = getCollection(t.getPriority(), true);
|
Collection<E> priority = getCollection(e.getPriority(), true);
|
||||||
return priority.add(t);
|
return priority.add(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -185,7 +185,7 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
private boolean removeInternal(Object o) {
|
private boolean removeInternal(Object o) {
|
||||||
if (o instanceof PriorityAware) {
|
if (o instanceof PriorityAware) {
|
||||||
PriorityAware priorityAware = (PriorityAware) o;
|
PriorityAware priorityAware = (PriorityAware) o;
|
||||||
Collection<T> priority = getCollection(priorityAware.getPriority(), false);
|
Collection<E> priority = getCollection(priorityAware.getPriority(), false);
|
||||||
boolean result = priority != null && priority.remove(priorityAware);
|
boolean result = priority != null && priority.remove(priorityAware);
|
||||||
if (priority != null && priority.isEmpty()) {
|
if (priority != null && priority.isEmpty()) {
|
||||||
removeCollection(priorityAware.getPriority());
|
removeCollection(priorityAware.getPriority());
|
||||||
|
@ -196,22 +196,22 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<T> removeCollection(int priority) {
|
private Collection<E> removeCollection(int priority) {
|
||||||
PriorityHolder<T>[] current = getArray();
|
PriorityHolder<E>[] current = getArray();
|
||||||
int len = current.length;
|
int len = current.length;
|
||||||
int low = 0;
|
int low = 0;
|
||||||
int high = len - 1;
|
int high = len - 1;
|
||||||
|
|
||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
int mid = (low + high) >>> 1;
|
int mid = (low + high) >>> 1;
|
||||||
PriorityHolder<T> midVal = current[mid];
|
PriorityHolder<E> midVal = current[mid];
|
||||||
|
|
||||||
if (midVal.getPriority() > priority)
|
if (midVal.getPriority() > priority)
|
||||||
low = mid + 1;
|
low = mid + 1;
|
||||||
else if (midVal.getPriority() < priority)
|
else if (midVal.getPriority() < priority)
|
||||||
high = mid - 1;
|
high = mid - 1;
|
||||||
else {
|
else {
|
||||||
PriorityHolder<T>[] newArray = newPrioritySetArrayInstance(len - 1);
|
PriorityHolder<E>[] newArray = newPrioritySetArrayInstance(len - 1);
|
||||||
System.arraycopy(current, 0, newArray, 0, mid);
|
System.arraycopy(current, 0, newArray, 0, mid);
|
||||||
System.arraycopy(current, mid + 1, newArray, mid, len - mid - 1);
|
System.arraycopy(current, mid + 1, newArray, mid, len - mid - 1);
|
||||||
setArray(newArray);
|
setArray(newArray);
|
||||||
|
@ -231,11 +231,11 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized boolean addAll(Collection<? extends T> c) {
|
public synchronized boolean addAll(Collection<? extends E> c) {
|
||||||
Objects.requireNonNull(c);
|
Objects.requireNonNull(c);
|
||||||
if (size() >= Integer.MAX_VALUE - c.size()) return false;
|
if (size() >= Integer.MAX_VALUE - c.size()) return false;
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (T e : c)
|
for (E e : c)
|
||||||
if (addInternal(e))
|
if (addInternal(e))
|
||||||
modified = true;
|
modified = true;
|
||||||
calcSize();
|
calcSize();
|
||||||
|
@ -259,8 +259,8 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
public synchronized boolean retainAll(Collection<?> c) {
|
public synchronized boolean retainAll(Collection<?> c) {
|
||||||
Objects.requireNonNull(c);
|
Objects.requireNonNull(c);
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
PriorityHolder<T>[] snapshot = getArray();
|
PriorityHolder<E>[] snapshot = getArray();
|
||||||
for (PriorityHolder<T> priorityHolder : snapshot) {
|
for (PriorityHolder<E> priorityHolder : snapshot) {
|
||||||
if (priorityHolder.getValues().retainAll(c)) {
|
if (priorityHolder.getValues().retainAll(c)) {
|
||||||
modified = true;
|
modified = true;
|
||||||
if (priorityHolder.getValues().isEmpty()) {
|
if (priorityHolder.getValues().isEmpty()) {
|
||||||
|
@ -274,8 +274,8 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void clear() {
|
public synchronized void clear() {
|
||||||
PriorityHolder<T>[] snapshot = getArray();
|
PriorityHolder<E>[] snapshot = getArray();
|
||||||
for (PriorityHolder<T> priorityHolder : snapshot) {
|
for (PriorityHolder<E> priorityHolder : snapshot) {
|
||||||
priorityHolder.getValues().clear();
|
priorityHolder.getValues().clear();
|
||||||
}
|
}
|
||||||
calcSize();
|
calcSize();
|
||||||
|
@ -288,14 +288,14 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
|
||||||
|
|
||||||
public boolean contains(PriorityAware priorityAware) {
|
public boolean contains(PriorityAware priorityAware) {
|
||||||
if (priorityAware == null) return false;
|
if (priorityAware == null) return false;
|
||||||
Collection<T> prioritySet = getCollection(priorityAware.getPriority(), false);
|
Collection<E> prioritySet = getCollection(priorityAware.getPriority(), false);
|
||||||
return prioritySet != null && prioritySet.contains(priorityAware);
|
return prioritySet != null && prioritySet.contains(priorityAware);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcSize() {
|
private void calcSize() {
|
||||||
PriorityHolder<T>[] current = getArray();
|
PriorityHolder<E>[] current = getArray();
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (PriorityHolder<T> priorityHolder : current) {
|
for (PriorityHolder<E> priorityHolder : current) {
|
||||||
size += priorityHolder.getValues().size();
|
size += priorityHolder.getValues().size();
|
||||||
}
|
}
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
|
|
@ -23,15 +23,15 @@ import java.util.function.ToLongFunction;
|
||||||
* and allows adding and removing of elements at both ends, and peeking.<br>
|
* and allows adding and removing of elements at both ends, and peeking.<br>
|
||||||
* Only {@link #size()} and {@link #isEmpty()} are safe to be called concurrently.
|
* Only {@link #size()} and {@link #isEmpty()} are safe to be called concurrently.
|
||||||
*/
|
*/
|
||||||
public interface PriorityLinkedList<T> {
|
public interface PriorityLinkedList<E> {
|
||||||
|
|
||||||
void addHead(T t, int priority);
|
void addHead(E e, int priority);
|
||||||
|
|
||||||
void addTail(T t, int priority);
|
void addTail(E e, int priority);
|
||||||
|
|
||||||
void addSorted(T t, int priority);
|
void addSorted(E e, int priority);
|
||||||
|
|
||||||
T poll();
|
E poll();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ public interface PriorityLinkedList<T> {
|
||||||
* @see LinkedList#setIDSupplier(ToLongFunction)
|
* @see LinkedList#setIDSupplier(ToLongFunction)
|
||||||
* @param supplier
|
* @param supplier
|
||||||
*/
|
*/
|
||||||
void setIDSupplier(ToLongFunction<T> supplier);
|
void setIDSupplier(ToLongFunction<E> supplier);
|
||||||
|
|
||||||
T removeWithID(long id);
|
E removeWithID(long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of this list.<br>
|
* Returns the size of this list.<br>
|
||||||
|
@ -49,7 +49,7 @@ public interface PriorityLinkedList<T> {
|
||||||
*/
|
*/
|
||||||
int size();
|
int size();
|
||||||
|
|
||||||
LinkedListIterator<T> iterator();
|
LinkedListIterator<E> iterator();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@code true} if empty, {@code false} otherwise.<br>
|
* Returns {@code true} if empty, {@code false} otherwise.<br>
|
||||||
|
|
|
@ -27,11 +27,11 @@ import java.util.function.ToLongFunction;
|
||||||
* <p>
|
* <p>
|
||||||
* It implements this by maintaining an individual LinkedBlockingDeque for each priority level.
|
* It implements this by maintaining an individual LinkedBlockingDeque for each priority level.
|
||||||
*/
|
*/
|
||||||
public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
public class PriorityLinkedListImpl<E> implements PriorityLinkedList<E> {
|
||||||
|
|
||||||
private static final AtomicIntegerFieldUpdater<PriorityLinkedListImpl> SIZE_UPDATER = AtomicIntegerFieldUpdater.newUpdater(PriorityLinkedListImpl.class, "size");
|
private static final AtomicIntegerFieldUpdater<PriorityLinkedListImpl> SIZE_UPDATER = AtomicIntegerFieldUpdater.newUpdater(PriorityLinkedListImpl.class, "size");
|
||||||
|
|
||||||
protected LinkedListImpl<T>[] levels;
|
protected LinkedListImpl<E>[] levels;
|
||||||
|
|
||||||
private volatile int size;
|
private volatile int size;
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public PriorityLinkedListImpl(final int priorities, Comparator<T> comparator) {
|
public PriorityLinkedListImpl(final int priorities, Comparator<E> comparator) {
|
||||||
levels = (LinkedListImpl<T>[]) Array.newInstance(LinkedListImpl.class, priorities);
|
levels = (LinkedListImpl<E>[]) Array.newInstance(LinkedListImpl.class, priorities);
|
||||||
|
|
||||||
for (int i = 0; i < priorities; i++) {
|
for (int i = 0; i < priorities; i++) {
|
||||||
levels[i] = new LinkedListImpl<>(comparator);
|
levels[i] = new LinkedListImpl<>(comparator);
|
||||||
|
@ -70,45 +70,45 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addHead(final T t, final int priority) {
|
public void addHead(final E e, final int priority) {
|
||||||
checkHighest(priority);
|
checkHighest(priority);
|
||||||
|
|
||||||
levels[priority].addHead(t);
|
levels[priority].addHead(e);
|
||||||
|
|
||||||
exclusiveIncrementSize(1);
|
exclusiveIncrementSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTail(final T t, final int priority) {
|
public void addTail(final E e, final int priority) {
|
||||||
checkHighest(priority);
|
checkHighest(priority);
|
||||||
|
|
||||||
levels[priority].addTail(t);
|
levels[priority].addTail(e);
|
||||||
|
|
||||||
exclusiveIncrementSize(1);
|
exclusiveIncrementSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addSorted(T t, int priority) {
|
public void addSorted(E e, int priority) {
|
||||||
checkHighest(priority);
|
checkHighest(priority);
|
||||||
|
|
||||||
levels[priority].addSorted(t);
|
levels[priority].addSorted(e);
|
||||||
|
|
||||||
exclusiveIncrementSize(1);
|
exclusiveIncrementSize(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setIDSupplier(ToLongFunction<T> supplier) {
|
public void setIDSupplier(ToLongFunction<E> supplier) {
|
||||||
for (LinkedList<T> list : levels) {
|
for (LinkedList<E> list : levels) {
|
||||||
list.setIDSupplier(supplier);
|
list.setIDSupplier(supplier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T removeWithID(long id) {
|
public E removeWithID(long id) {
|
||||||
// we start at 4 just as an optimization, since most times we only use level 4 as the level on messages
|
// we start at 4 just as an optimization, since most times we only use level 4 as the level on messages
|
||||||
if (levels.length > 4) {
|
if (levels.length > 4) {
|
||||||
for (int l = 4; l < levels.length; l++) {
|
for (int l = 4; l < levels.length; l++) {
|
||||||
T removed = levels[l].removeWithID(id);
|
E removed = levels[l].removeWithID(id);
|
||||||
if (removed != null) {
|
if (removed != null) {
|
||||||
exclusiveIncrementSize(-1);
|
exclusiveIncrementSize(-1);
|
||||||
return removed;
|
return removed;
|
||||||
|
@ -117,7 +117,7 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int l = Math.min(3, levels.length); l >= 0; l--) {
|
for (int l = Math.min(3, levels.length); l >= 0; l--) {
|
||||||
T removed = levels[l].removeWithID(id);
|
E removed = levels[l].removeWithID(id);
|
||||||
if (removed != null) {
|
if (removed != null) {
|
||||||
exclusiveIncrementSize(-1);
|
exclusiveIncrementSize(-1);
|
||||||
return removed;
|
return removed;
|
||||||
|
@ -129,8 +129,8 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T poll() {
|
public E poll() {
|
||||||
T t = null;
|
E e = null;
|
||||||
|
|
||||||
// We are just using a simple prioritization algorithm:
|
// We are just using a simple prioritization algorithm:
|
||||||
// Highest priority refs always get returned first.
|
// Highest priority refs always get returned first.
|
||||||
|
@ -139,12 +139,12 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
// TODO - A better prioritization algorithm
|
// TODO - A better prioritization algorithm
|
||||||
|
|
||||||
for (int i = highestPriority; i >= 0; i--) {
|
for (int i = highestPriority; i >= 0; i--) {
|
||||||
LinkedListImpl<T> ll = levels[i];
|
LinkedListImpl<E> ll = levels[i];
|
||||||
|
|
||||||
if (ll.size() != 0) {
|
if (ll.size() != 0) {
|
||||||
t = ll.poll();
|
e = ll.poll();
|
||||||
|
|
||||||
if (t != null) {
|
if (e != null) {
|
||||||
exclusiveIncrementSize(-1);
|
exclusiveIncrementSize(-1);
|
||||||
|
|
||||||
if (ll.size() == 0) {
|
if (ll.size() == 0) {
|
||||||
|
@ -158,12 +158,12 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clear() {
|
public void clear() {
|
||||||
for (LinkedListImpl<T> list : levels) {
|
for (LinkedListImpl<E> list : levels) {
|
||||||
list.clear();
|
list.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,17 +189,17 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LinkedListIterator<T> iterator() {
|
public LinkedListIterator<E> iterator() {
|
||||||
return new PriorityLinkedListIterator();
|
return new PriorityLinkedListIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
private class PriorityLinkedListIterator implements LinkedListIterator<T> {
|
private class PriorityLinkedListIterator implements LinkedListIterator<E> {
|
||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
private final LinkedListIterator<T>[] cachedIters = new LinkedListIterator[levels.length];
|
private final LinkedListIterator<E>[] cachedIters = new LinkedListIterator[levels.length];
|
||||||
|
|
||||||
private LinkedListIterator<T> lastIter;
|
private LinkedListIterator<E> lastIter;
|
||||||
|
|
||||||
private int resetCount = lastReset;
|
private int resetCount = lastReset;
|
||||||
|
|
||||||
|
@ -229,7 +229,7 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
closed = true;
|
closed = true;
|
||||||
lastIter = null;
|
lastIter = null;
|
||||||
|
|
||||||
for (LinkedListIterator<T> iter : cachedIters) {
|
for (LinkedListIterator<E> iter : cachedIters) {
|
||||||
if (iter != null) {
|
if (iter != null) {
|
||||||
iter.close();
|
iter.close();
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T next() {
|
public E next() {
|
||||||
if (lastIter == null) {
|
if (lastIter == null) {
|
||||||
throw new NoSuchElementException();
|
throw new NoSuchElementException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,12 +34,12 @@ import java.util.function.Predicate;
|
||||||
* From the memory footprint's point of view, this list won't remove the last remaining array although empty to optimize
|
* From the memory footprint's point of view, this list won't remove the last remaining array although empty to optimize
|
||||||
* the case where its capacity would be enough to hold incoming elements, hence saving a new array allocation.
|
* the case where its capacity would be enough to hold incoming elements, hence saving a new array allocation.
|
||||||
*/
|
*/
|
||||||
public final class SparseArrayLinkedList<T> {
|
public final class SparseArrayLinkedList<E> {
|
||||||
|
|
||||||
// the whole chunk fit into 1 or 2 cache lines depending if JVM COOPS are used
|
// the whole chunk fit into 1 or 2 cache lines depending if JVM COOPS are used
|
||||||
private static final int SPARSE_ARRAY_DEFAULT_CAPACITY = 16;
|
private static final int SPARSE_ARRAY_DEFAULT_CAPACITY = 16;
|
||||||
|
|
||||||
private static final class SparseArray<T> {
|
private static final class SparseArray<E> {
|
||||||
|
|
||||||
private final Object[] elements;
|
private final Object[] elements;
|
||||||
private int size;
|
private int size;
|
||||||
|
@ -52,18 +52,18 @@ public final class SparseArrayLinkedList<T> {
|
||||||
tail = 0;
|
tail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean add(T e) {
|
private boolean add(E e) {
|
||||||
final int capacity = elements.length;
|
final int capacity = elements.length;
|
||||||
if (tail == capacity) {
|
if (tail == capacity) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
elements[tail] = (T) e;
|
elements[tail] = (E) e;
|
||||||
tail++;
|
tail++;
|
||||||
size++;
|
size++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int remove(Predicate<? super T> filter) {
|
private int remove(Predicate<? super E> filter) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
// this shouldn't happen: the chunk should be removed if empty
|
// this shouldn't happen: the chunk should be removed if empty
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -75,7 +75,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
int visited = 0;
|
int visited = 0;
|
||||||
final int originalSize = size;
|
final int originalSize = size;
|
||||||
for (int i = 0, capacity = elements.length; i < capacity; i++) {
|
for (int i = 0, capacity = elements.length; i < capacity; i++) {
|
||||||
final T e = (T) elements[i];
|
final E e = (E) elements[i];
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
if (filter.test(e)) {
|
if (filter.test(e)) {
|
||||||
elements[i] = null;
|
elements[i] = null;
|
||||||
|
@ -100,7 +100,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int clear(Consumer<? super T> consumer) {
|
public int clear(Consumer<? super E> consumer) {
|
||||||
final int originalSize = size;
|
final int originalSize = size;
|
||||||
if (originalSize == 0) {
|
if (originalSize == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -108,7 +108,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
int visited = 0;
|
int visited = 0;
|
||||||
final Object[] elements = this.elements;
|
final Object[] elements = this.elements;
|
||||||
for (int i = 0, capacity = elements.length; i < capacity; i++) {
|
for (int i = 0, capacity = elements.length; i < capacity; i++) {
|
||||||
final T e = (T) elements[i];
|
final E e = (E) elements[i];
|
||||||
if (e != null) {
|
if (e != null) {
|
||||||
if (consumer != null) {
|
if (consumer != null) {
|
||||||
consumer.accept(e);
|
consumer.accept(e);
|
||||||
|
@ -131,14 +131,14 @@ public final class SparseArrayLinkedList<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> long removeFromSparseArrayList(List<SparseArray<T>> sparseArrayList, Predicate<? super T> filter) {
|
public static <E> long removeFromSparseArrayList(List<SparseArray<E>> sparseArrayList, Predicate<? super E> filter) {
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
long removed = 0;
|
long removed = 0;
|
||||||
Iterator<SparseArray<T>> iter = sparseArrayList.iterator();
|
Iterator<SparseArray<E>> iter = sparseArrayList.iterator();
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
final SparseArray<T> sparseArray = iter.next();
|
final SparseArray<E> sparseArray = iter.next();
|
||||||
final int justRemoved = sparseArray.remove(filter);
|
final int justRemoved = sparseArray.remove(filter);
|
||||||
removed += justRemoved;
|
removed += justRemoved;
|
||||||
if (justRemoved > 0) {
|
if (justRemoved > 0) {
|
||||||
|
@ -153,23 +153,23 @@ public final class SparseArrayLinkedList<T> {
|
||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> void addToSparseArrayList(List<SparseArray<T>> sparseArrayList, T e, int sparseArrayCapacity) {
|
public static <E> void addToSparseArrayList(List<SparseArray<E>> sparseArrayList, E e, int sparseArrayCapacity) {
|
||||||
final int size = sparseArrayList.size();
|
final int size = sparseArrayList.size();
|
||||||
// LinkedList::get(size-1) is fast as LinkedList::getLast
|
// LinkedList::get(size-1) is fast as LinkedList::getLast
|
||||||
if (size == 0 || !sparseArrayList.get(size - 1).add(e)) {
|
if (size == 0 || !sparseArrayList.get(size - 1).add(e)) {
|
||||||
final SparseArray<T> sparseArray = new SparseArray<>(sparseArrayCapacity);
|
final SparseArray<E> sparseArray = new SparseArray<>(sparseArrayCapacity);
|
||||||
sparseArray.add(e);
|
sparseArray.add(e);
|
||||||
sparseArrayList.add(sparseArray);
|
sparseArrayList.add(sparseArray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> long clearSparseArrayList(List<SparseArray<T>> sparseArrayList, Consumer<? super T> consumer) {
|
public static <E> long clearSparseArrayList(List<SparseArray<E>> sparseArrayList, Consumer<? super E> consumer) {
|
||||||
final int size = sparseArrayList.size();
|
final int size = sparseArrayList.size();
|
||||||
long count = 0;
|
long count = 0;
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
for (int i = 0; i < size - 1; i++) {
|
for (int i = 0; i < size - 1; i++) {
|
||||||
// LinkedList::remove(0) is fast as LinkedList::getFirst
|
// LinkedList::remove(0) is fast as LinkedList::getFirst
|
||||||
final SparseArray<T> removed = sparseArrayList.remove(0);
|
final SparseArray<E> removed = sparseArrayList.remove(0);
|
||||||
count += removed.clear(consumer);
|
count += removed.clear(consumer);
|
||||||
}
|
}
|
||||||
// LinkedList::get(0) is fast as LinkedList::getFirst
|
// LinkedList::get(0) is fast as LinkedList::getFirst
|
||||||
|
@ -178,7 +178,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final LinkedList<SparseArray<T>> list;
|
private final LinkedList<SparseArray<E>> list;
|
||||||
private final int sparseArrayCapacity;
|
private final int sparseArrayCapacity;
|
||||||
private long size;
|
private long size;
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
/**
|
/**
|
||||||
* Appends {@code e} to the end of this list.
|
* Appends {@code e} to the end of this list.
|
||||||
*/
|
*/
|
||||||
public void add(T e) {
|
public void add(E e) {
|
||||||
Objects.requireNonNull(e, "e cannot be null");
|
Objects.requireNonNull(e, "e cannot be null");
|
||||||
addToSparseArrayList(list, e, sparseArrayCapacity);
|
addToSparseArrayList(list, e, sparseArrayCapacity);
|
||||||
size++;
|
size++;
|
||||||
|
@ -207,7 +207,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
/**
|
/**
|
||||||
* Removes any element of the list matching the given predicate.
|
* Removes any element of the list matching the given predicate.
|
||||||
*/
|
*/
|
||||||
public long remove(Predicate<? super T> filter) {
|
public long remove(Predicate<? super E> filter) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ public final class SparseArrayLinkedList<T> {
|
||||||
/**
|
/**
|
||||||
* Clear while consuming (using the given {@code consumer} all the elements of this list.
|
* Clear while consuming (using the given {@code consumer} all the elements of this list.
|
||||||
*/
|
*/
|
||||||
public long clear(Consumer<? super T> consumer) {
|
public long clear(Consumer<? super E> consumer) {
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue