ARTEMIS-3373 Using consistent template terminology under the collections package

This commit is contained in:
Clebert Suconic 2021-07-02 10:51:39 -04:00 committed by clebertsuconic
parent 200e436931
commit 4d7c6cc188
12 changed files with 162 additions and 161 deletions

View File

@ -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;

View File

@ -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++;

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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);
} }

View File

@ -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;

View File

@ -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>

View File

@ -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();
} }

View File

@ -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;
} }