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.
* It achieves this though by moving end position mark to the the current cursors position,
* 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 int cursor = 0;
@ -36,7 +36,7 @@ public class ArrayResettableIterator<T> implements ResettableIterator<T> {
reset();
}
public static <T> ResettableIterator<T> iterator(Collection<T> collection) {
public static <E> ResettableIterator<E> iterator(Collection<E> collection) {
return new ArrayResettableIterator<>(collection.toArray());
}
@ -52,11 +52,12 @@ public class ArrayResettableIterator<T> implements ResettableIterator<T> {
}
@Override
public T next() {
public E next() {
if (!hasNext) {
throw new IllegalStateException();
}
@SuppressWarnings("unchecked") T result = (T) array[cursor];
@SuppressWarnings("unchecked")
E result = (E) array[cursor];
cursor++;
if (cursor == array.length) {
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>
* 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;
final AtomicChunk<T> prev;
AtomicChunk<E> next = null;
final AtomicChunk<E> prev;
final int index;
AtomicChunk(int index, AtomicChunk<T> prev, int length) {
AtomicChunk(int index, AtomicChunk<E> prev, int length) {
super(length);
this.index = index;
this.prev = prev;
@ -48,9 +48,9 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
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'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.
*/
public void addAll(T[] elements) {
for (T e : elements) {
public void addAll(E[] elements) {
for (E e : elements) {
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.
*/
public T get(int index) {
public E get(int index) {
if (index < 0) {
return null;
}
@ -104,7 +104,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
if (index >= lastIndex) {
return null;
}
final AtomicChunk<T> buffer;
final AtomicChunk<E> buffer;
final int offset;
if (index >= chunkSize) {
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
* 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;
//fast division by a power of 2
final int chunkIndex = index >> chunkSizeLog2;
//size is never allowed to be > Integer.MAX_VALUE
final int lastChunkIndex = (int) lastIndex >> chunkSizeLog2;
int distance = chunkIndex;
AtomicChunk<T> buffer = null;
AtomicChunk<E> buffer = null;
boolean forward = true;
int distanceFromLast = lastChunkIndex - chunkIndex;
//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
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
distanceFromLast = lastBuffer.index - chunkIndex;
if (distanceFromLast < distance) {
@ -161,7 +161,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
*
* @throws NullPointerException if {@code e} is {@code null}
**/
public void add(T e) {
public void add(E e) {
Objects.requireNonNull(e);
while (true) {
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");
}
//load acquire the current lastBuffer
final AtomicChunk<T> lastBuffer = this.lastBuffer;
final AtomicChunk<E> lastBuffer = this.lastBuffer;
final int offset = (int) (validLastIndex & chunkMask);
//only the first attempt to add an element to a chunk can attempt to resize
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
if (!LAST_INDEX_UPDATER.compareAndSet(this, lastIndex, lastIndex + 1)) {
return false;
}
final AtomicChunk<T> newChunk;
final AtomicChunk<E> newChunk;
try {
final int index = (int) (validLastIndex >> chunkSizeLog2);
newChunk = new AtomicChunk<>(index, lastBuffer, chunkSize);
@ -222,7 +222,7 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
return true;
}
public T[] toArray(IntFunction<T[]> arrayAllocator) {
public E[] toArray(IntFunction<E[]> arrayAllocator) {
return toArray(arrayAllocator, 0);
}
@ -231,21 +231,21 @@ public final class ConcurrentAppendOnlyChunkedList<T> {
* 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.
*/
public T[] toArray(IntFunction<T[]> arrayAllocator, int startIndex) {
public E[] toArray(IntFunction<E[]> arrayAllocator, int startIndex) {
if (startIndex < 0) {
throw new ArrayIndexOutOfBoundsException("startIndex must be >= 0");
}
final long lastIndex = getValidLastIndex();
assert lastIndex <= Integer.MAX_VALUE;
final int size = (int) lastIndex;
final T[] elements = arrayAllocator.apply(size);
final E[] elements = arrayAllocator.apply(size);
if (startIndex + size > elements.length) {
throw new ArrayIndexOutOfBoundsException();
}
//fast division by a power of 2
final int chunkSize = this.chunkSize;
final int chunks = size > chunkSize ? size >> chunkSizeLog2 : 0;
AtomicChunk<T> buffer = firstBuffer;
AtomicChunk<E> buffer = firstBuffer;
int elementIndex = startIndex;
for (int i = 0; i < chunks; i++) {
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
private static <T> T pollElement(AtomicChunk<T> buffer, int i) {
T e;
private static <E> E pollElement(AtomicChunk<E> buffer, int i) {
E e;
while ((e = buffer.get(i)) == null) {
}
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++) {
final T e = pollElement(buffer, j);
final E e = pollElement(buffer, j);
assert e != null;
elements[elementNumber] = e;
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;
}

View File

@ -372,30 +372,30 @@ public class LinkedListImpl<E> implements LinkedList<E> {
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
private NodeHolder(T e) {
private NodeHolder(E e) {
val = e;
}
@Override
protected T val() {
protected E 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 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");
if (o instanceof Node) {
final Node node = (Node) o;
@ -410,15 +410,15 @@ public class LinkedListImpl<E> implements LinkedList<E> {
}
@SuppressWarnings("unchecked")
protected T val() {
return (T) this;
protected E val() {
return (E) this;
}
protected final LinkedListImpl.Node<T> next() {
protected final LinkedListImpl.Node<E> next() {
return next;
}
protected final LinkedListImpl.Node<T> prev() {
protected final LinkedListImpl.Node<E> prev() {
return prev;
}

View File

@ -405,14 +405,14 @@ public class LongHashSet extends AbstractSet<Long> implements Serializable {
*/
@SuppressWarnings("unchecked")
@Override
public <T> T[] toArray(final T[] a) {
public <E> E[] toArray(final E[] a) {
final Class<?> componentType = a.getClass().getComponentType();
if (!componentType.isAssignableFrom(Long.class)) {
throw new ArrayStoreException("cannot store Longs in array of type " + componentType);
}
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);
return arrayCopy;

View File

@ -21,11 +21,11 @@ import java.util.Iterator;
/**
* 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);
}
}

View File

@ -21,10 +21,10 @@ import java.util.Iterator;
/**
* 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
*/
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 int index = -1;
@ -52,7 +52,7 @@ abstract class MultiIteratorBase<T, I extends Iterator<T>> implements Iterator<T
}
@Override
public T next() {
public E next() {
while (true) {
if (index != -1) {
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.
* 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);
}

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.
*
* @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 volatile PriorityHolder<T>[] priorityHolders = newPrioritySetArrayInstance(0);
private final Supplier<Collection<E>> supplier;
private volatile PriorityHolder<E>[] priorityHolders = newPrioritySetArrayInstance(0);
private volatile int size;
private void setArray(PriorityHolder<T>[] priorityHolders) {
private void setArray(PriorityHolder<E>[] priorityHolders) {
this.priorityHolders = priorityHolders;
}
private PriorityHolder<T>[] getArray() {
private PriorityHolder<E>[] getArray() {
return priorityHolders;
}
public PriorityCollection(Supplier<Collection<T>> supplier) {
public PriorityCollection(Supplier<Collection<E>> supplier) {
this.supplier = supplier;
}
@SuppressWarnings("unchecked")
private static <T> PriorityHolder<T>[] newPrioritySetArrayInstance(int length) {
return (PriorityHolder<T>[]) Array.newInstance(PriorityHolder.class, length);
private static <E> PriorityHolder<E>[] newPrioritySetArrayInstance(int length) {
return (PriorityHolder<E>[]) Array.newInstance(PriorityHolder.class, length);
}
@Override
@ -75,20 +75,20 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
public Set<Integer> getPriorites() {
PriorityHolder<T>[] snapshot = getArray();
PriorityHolder<E>[] snapshot = getArray();
return Arrays.stream(snapshot).map(PriorityAware::getPriority).collect(Collectors.toSet());
}
@Override
public Iterator<T> iterator() {
Iterator<T>[] iterators = getIterators();
public Iterator<E> iterator() {
Iterator<E>[] iterators = getIterators();
return new MultiIterator<>(iterators);
}
private Iterator<T>[] getIterators() {
PriorityHolder<T>[] snapshot = this.getArray();
private Iterator<E>[] getIterators() {
PriorityHolder<E>[] snapshot = this.getArray();
int size = snapshot.length;
Iterator<T>[] iterators = newIteratorArrayInstance(size);
Iterator<E>[] iterators = newIteratorArrayInstance(size);
for (int i = 0; i < size; i++) {
iterators[i] = snapshot[i].getValues().iterator();
}
@ -96,18 +96,18 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
@SuppressWarnings("unchecked")
private static <T> Iterator<T>[] newIteratorArrayInstance(int length) {
return (Iterator<T>[]) Array.newInstance(Iterator.class, length);
private static <E> Iterator<E>[] newIteratorArrayInstance(int length) {
return (Iterator<E>[]) Array.newInstance(Iterator.class, length);
}
public ResettableIterator<T> resettableIterator() {
return new MultiResettableIterator<T>(getResettableIterators());
public ResettableIterator<E> resettableIterator() {
return new MultiResettableIterator<E>(getResettableIterators());
}
private ResettableIterator<T>[] getResettableIterators() {
PriorityHolder<T>[] snapshot = this.getArray();
private ResettableIterator<E>[] getResettableIterators() {
PriorityHolder<E>[] snapshot = this.getArray();
int size = snapshot.length;
ResettableIterator<T>[] iterators = newResettableIteratorArrayInstance(size);
ResettableIterator<E>[] iterators = newResettableIteratorArrayInstance(size);
for (int i = 0; i < size; i++) {
iterators[i] = ArrayResettableIterator.iterator(snapshot[i].getValues());
}
@ -115,28 +115,28 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
@SuppressWarnings("unchecked")
private static <T> ResettableIterator<T>[] newResettableIteratorArrayInstance(int length) {
return (ResettableIterator<T>[]) Array.newInstance(ResettableIterator.class, length);
private static <E> ResettableIterator<E>[] newResettableIteratorArrayInstance(int length) {
return (ResettableIterator<E>[]) Array.newInstance(ResettableIterator.class, length);
}
@Override
public void forEach(Consumer<? super T> action) {
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
PriorityHolder<T>[] current = getArray();
PriorityHolder<E>[] current = getArray();
int len = current.length;
for (int i = 0; i < len; ++i) {
current[i].getValues().forEach(action);
}
}
private Collection<T> getCollection(int priority, boolean createIfMissing) {
PriorityHolder<T>[] current = getArray();
private Collection<E> getCollection(int priority, boolean createIfMissing) {
PriorityHolder<E>[] current = getArray();
int low = 0;
int high = current.length - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
PriorityHolder<T> midVal = current[mid];
PriorityHolder<E> midVal = current[mid];
if (midVal.getPriority() > priority)
low = mid + 1;
@ -147,14 +147,14 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
if (createIfMissing) {
PriorityHolder<T>[] newArray = newPrioritySetArrayInstance(current.length + 1);
PriorityHolder<E>[] newArray = newPrioritySetArrayInstance(current.length + 1);
if (low > 0) {
System.arraycopy(current, 0, newArray, 0, low);
}
if (current.length - low > 0) {
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);
return newArray[low].getValues();
}
@ -162,17 +162,17 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
@Override
public synchronized boolean add(T t) {
public synchronized boolean add(E e) {
if (size() == Integer.MAX_VALUE) return false;
boolean result = addInternal(t);
boolean result = addInternal(e);
calcSize();
return result;
}
private boolean addInternal(T t) {
if (t == null) return false;
Collection<T> priority = getCollection(t.getPriority(), true);
return priority.add(t);
private boolean addInternal(E e) {
if (e == null) return false;
Collection<E> priority = getCollection(e.getPriority(), true);
return priority.add(e);
}
@Override
@ -185,7 +185,7 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
private boolean removeInternal(Object o) {
if (o instanceof PriorityAware) {
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);
if (priority != null && priority.isEmpty()) {
removeCollection(priorityAware.getPriority());
@ -196,22 +196,22 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
}
private Collection<T> removeCollection(int priority) {
PriorityHolder<T>[] current = getArray();
private Collection<E> removeCollection(int priority) {
PriorityHolder<E>[] current = getArray();
int len = current.length;
int low = 0;
int high = len - 1;
while (low <= high) {
int mid = (low + high) >>> 1;
PriorityHolder<T> midVal = current[mid];
PriorityHolder<E> midVal = current[mid];
if (midVal.getPriority() > priority)
low = mid + 1;
else if (midVal.getPriority() < priority)
high = mid - 1;
else {
PriorityHolder<T>[] newArray = newPrioritySetArrayInstance(len - 1);
PriorityHolder<E>[] newArray = newPrioritySetArrayInstance(len - 1);
System.arraycopy(current, 0, newArray, 0, mid);
System.arraycopy(current, mid + 1, newArray, mid, len - mid - 1);
setArray(newArray);
@ -231,11 +231,11 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
}
@Override
public synchronized boolean addAll(Collection<? extends T> c) {
public synchronized boolean addAll(Collection<? extends E> c) {
Objects.requireNonNull(c);
if (size() >= Integer.MAX_VALUE - c.size()) return false;
boolean modified = false;
for (T e : c)
for (E e : c)
if (addInternal(e))
modified = true;
calcSize();
@ -259,8 +259,8 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
public synchronized boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
boolean modified = false;
PriorityHolder<T>[] snapshot = getArray();
for (PriorityHolder<T> priorityHolder : snapshot) {
PriorityHolder<E>[] snapshot = getArray();
for (PriorityHolder<E> priorityHolder : snapshot) {
if (priorityHolder.getValues().retainAll(c)) {
modified = true;
if (priorityHolder.getValues().isEmpty()) {
@ -274,8 +274,8 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
@Override
public synchronized void clear() {
PriorityHolder<T>[] snapshot = getArray();
for (PriorityHolder<T> priorityHolder : snapshot) {
PriorityHolder<E>[] snapshot = getArray();
for (PriorityHolder<E> priorityHolder : snapshot) {
priorityHolder.getValues().clear();
}
calcSize();
@ -288,14 +288,14 @@ public class PriorityCollection<T extends PriorityAware> extends AbstractCollect
public boolean contains(PriorityAware priorityAware) {
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);
}
private void calcSize() {
PriorityHolder<T>[] current = getArray();
PriorityHolder<E>[] current = getArray();
int size = 0;
for (PriorityHolder<T> priorityHolder : current) {
for (PriorityHolder<E> priorityHolder : current) {
size += priorityHolder.getValues().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>
* 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();
@ -39,9 +39,9 @@ public interface PriorityLinkedList<T> {
* @see LinkedList#setIDSupplier(ToLongFunction)
* @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>
@ -49,7 +49,7 @@ public interface PriorityLinkedList<T> {
*/
int size();
LinkedListIterator<T> iterator();
LinkedListIterator<E> iterator();
/**
* Returns {@code true} if empty, {@code false} otherwise.<br>

View File

@ -27,11 +27,11 @@ import java.util.function.ToLongFunction;
* <p>
* 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");
protected LinkedListImpl<T>[] levels;
protected LinkedListImpl<E>[] levels;
private volatile int size;
@ -46,8 +46,8 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
}
public PriorityLinkedListImpl(final int priorities, Comparator<T> comparator) {
levels = (LinkedListImpl<T>[]) Array.newInstance(LinkedListImpl.class, priorities);
public PriorityLinkedListImpl(final int priorities, Comparator<E> comparator) {
levels = (LinkedListImpl<E>[]) Array.newInstance(LinkedListImpl.class, priorities);
for (int i = 0; i < priorities; i++) {
levels[i] = new LinkedListImpl<>(comparator);
@ -70,45 +70,45 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
}
@Override
public void addHead(final T t, final int priority) {
public void addHead(final E e, final int priority) {
checkHighest(priority);
levels[priority].addHead(t);
levels[priority].addHead(e);
exclusiveIncrementSize(1);
}
@Override
public void addTail(final T t, final int priority) {
public void addTail(final E e, final int priority) {
checkHighest(priority);
levels[priority].addTail(t);
levels[priority].addTail(e);
exclusiveIncrementSize(1);
}
@Override
public void addSorted(T t, int priority) {
public void addSorted(E e, int priority) {
checkHighest(priority);
levels[priority].addSorted(t);
levels[priority].addSorted(e);
exclusiveIncrementSize(1);
}
@Override
public void setIDSupplier(ToLongFunction<T> supplier) {
for (LinkedList<T> list : levels) {
public void setIDSupplier(ToLongFunction<E> supplier) {
for (LinkedList<E> list : levels) {
list.setIDSupplier(supplier);
}
}
@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
if (levels.length > 4) {
for (int l = 4; l < levels.length; l++) {
T removed = levels[l].removeWithID(id);
E removed = levels[l].removeWithID(id);
if (removed != null) {
exclusiveIncrementSize(-1);
return removed;
@ -117,7 +117,7 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
}
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) {
exclusiveIncrementSize(-1);
return removed;
@ -129,8 +129,8 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
@Override
public T poll() {
T t = null;
public E poll() {
E e = null;
// We are just using a simple prioritization algorithm:
// Highest priority refs always get returned first.
@ -139,12 +139,12 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
// TODO - A better prioritization algorithm
for (int i = highestPriority; i >= 0; i--) {
LinkedListImpl<T> ll = levels[i];
LinkedListImpl<E> ll = levels[i];
if (ll.size() != 0) {
t = ll.poll();
e = ll.poll();
if (t != null) {
if (e != null) {
exclusiveIncrementSize(-1);
if (ll.size() == 0) {
@ -158,12 +158,12 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
}
}
return t;
return e;
}
@Override
public void clear() {
for (LinkedListImpl<T> list : levels) {
for (LinkedListImpl<E> list : levels) {
list.clear();
}
@ -189,17 +189,17 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
}
@Override
public LinkedListIterator<T> iterator() {
public LinkedListIterator<E> iterator() {
return new PriorityLinkedListIterator();
}
private class PriorityLinkedListIterator implements LinkedListIterator<T> {
private class PriorityLinkedListIterator implements LinkedListIterator<E> {
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;
@ -229,7 +229,7 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
closed = true;
lastIter = null;
for (LinkedListIterator<T> iter : cachedIters) {
for (LinkedListIterator<E> iter : cachedIters) {
if (iter != null) {
iter.close();
}
@ -274,7 +274,7 @@ public class PriorityLinkedListImpl<T> implements PriorityLinkedList<T> {
}
@Override
public T next() {
public E next() {
if (lastIter == null) {
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
* 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
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 int size;
@ -52,18 +52,18 @@ public final class SparseArrayLinkedList<T> {
tail = 0;
}
private boolean add(T e) {
private boolean add(E e) {
final int capacity = elements.length;
if (tail == capacity) {
return false;
}
elements[tail] = (T) e;
elements[tail] = (E) e;
tail++;
size++;
return true;
}
private int remove(Predicate<? super T> filter) {
private int remove(Predicate<? super E> filter) {
if (size == 0) {
// this shouldn't happen: the chunk should be removed if empty
return 0;
@ -75,7 +75,7 @@ public final class SparseArrayLinkedList<T> {
int visited = 0;
final int originalSize = size;
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 (filter.test(e)) {
elements[i] = null;
@ -100,7 +100,7 @@ public final class SparseArrayLinkedList<T> {
return removed;
}
public int clear(Consumer<? super T> consumer) {
public int clear(Consumer<? super E> consumer) {
final int originalSize = size;
if (originalSize == 0) {
return 0;
@ -108,7 +108,7 @@ public final class SparseArrayLinkedList<T> {
int visited = 0;
final Object[] elements = this.elements;
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 (consumer != null) {
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) {
return 0;
}
long removed = 0;
Iterator<SparseArray<T>> iter = sparseArrayList.iterator();
Iterator<SparseArray<E>> iter = sparseArrayList.iterator();
while (iter.hasNext()) {
final SparseArray<T> sparseArray = iter.next();
final SparseArray<E> sparseArray = iter.next();
final int justRemoved = sparseArray.remove(filter);
removed += justRemoved;
if (justRemoved > 0) {
@ -153,23 +153,23 @@ public final class SparseArrayLinkedList<T> {
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();
// LinkedList::get(size-1) is fast as LinkedList::getLast
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);
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();
long count = 0;
if (size > 0) {
for (int i = 0; i < size - 1; i++) {
// 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);
}
// LinkedList::get(0) is fast as LinkedList::getFirst
@ -178,7 +178,7 @@ public final class SparseArrayLinkedList<T> {
return count;
}
private final LinkedList<SparseArray<T>> list;
private final LinkedList<SparseArray<E>> list;
private final int sparseArrayCapacity;
private long size;
@ -198,7 +198,7 @@ public final class SparseArrayLinkedList<T> {
/**
* 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");
addToSparseArrayList(list, e, sparseArrayCapacity);
size++;
@ -207,7 +207,7 @@ public final class SparseArrayLinkedList<T> {
/**
* 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) {
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.
*/
public long clear(Consumer<? super T> consumer) {
public long clear(Consumer<? super E> consumer) {
if (size == 0) {
return 0;
}