com.yahoo.concurrent.ThreadRobustList Maven / Gradle / Ivy
Show all versions of vespajlib Show documentation
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.concurrent;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* A list which tolerates concurrent adds from one other thread while it is
* read. More precisely: This list is guaranteed to provide a self-consistent
* read view regardless of the internal order in which the primitive mutating
* operations on it are observed from the reading thread.
*
* This is useful for traced information as there may be timed out threads
* working on the structure after it is returned upwards for consumption.
*
* @author Steinar Knutsen
* @author bratseth
*/
public class ThreadRobustList implements Iterable {
private Object[] items;
/** Index of the next item */
private int next = 0;
public ThreadRobustList() {
this(10);
}
public ThreadRobustList(final int initialCapacity) {
items = new Object[initialCapacity];
}
public void add(final T item) {
Object[] workItems = items;
if (next >= items.length) {
final int newLength = 20 + items.length * 2;
workItems = Arrays.copyOf(workItems, newLength);
workItems[next++] = item;
items = workItems;
} else {
workItems[next++] = item;
}
}
/**
* Returns an iterator over the elements of this. This iterator does not
* support remove.
*/
@Override
public Iterator iterator() {
return new ThreadRobustIterator(items);
}
/**
* Returns an iterator over the elements of this, starting at the last
* element and working backwards. This iterator does not support remove.
*/
public Iterator reverseIterator() {
return new ThreadRobustReverseIterator(items);
}
public boolean isEmpty() {
return next == 0;
}
private class ThreadRobustIterator implements Iterator {
private final Object[] items;
private int nextIndex = 0;
public ThreadRobustIterator(final Object[] items) {
this.items = items;
}
public @Override
void remove() {
throw new UnsupportedOperationException(
"remove() is not supported on thread robust list iterators");
}
@SuppressWarnings("unchecked")
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException("No more elements");
}
return (T) items[nextIndex++];
}
@Override
public boolean hasNext() {
if (nextIndex >= items.length) {
return false;
}
if (items[nextIndex] == null) {
return false;
}
return true;
}
}
private class ThreadRobustReverseIterator implements Iterator {
private final Object[] items;
private int nextIndex;
public ThreadRobustReverseIterator(final Object[] items) {
this.items = items;
nextIndex = findLastAssignedIndex(items);
}
private int findLastAssignedIndex(final Object[] items) {
for (int i = items.length - 1; i >= 0; i--) {
if (items[i] != null) {
return i;
}
}
return -1;
}
public @Override
void remove() {
throw new UnsupportedOperationException(
"remove() is not supported on thread robust list iterators");
}
@SuppressWarnings("unchecked")
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException("No more elements");
}
return (T) items[nextIndex--];
}
@Override
public boolean hasNext() {
return nextIndex >= 0;
}
}
}