AccumulatorCompleteRange.java
package handist.collections.accumulator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import handist.collections.Chunk;
import handist.collections.ChunkedList;
import handist.collections.LongRange;
/**
* Variation of {@link Accumulator} which creates accumulators for each range
* specified during the construction of this object.
*
* @param <A> the accumulator type used to store information
*/
public class AccumulatorCompleteRange<A> extends Accumulator<A> {
private class CompleteRangeTLA implements ThreadLocalAccumulator<A> {
ChunkedList<A> accumulators;
public CompleteRangeTLA() {
accumulators = new ChunkedList<>();
for (final LongRange range : rangesToAllocate) {
final Chunk<A> accChunk = new Chunk<>(range, initFunc);
accumulators.add(accChunk);
}
}
@Override
public A acquire(long idx) {
return accumulators.get(idx);
}
@Override
public ChunkedList<A> acquire(LongRange range) {
return accumulators.subList(range);
}
@Override
public ChunkedList<A> getChunkedList() {
return accumulators;
}
@Override
public Collection<LongRange> ranges() {
return accumulators.ranges();
}
}
/**
* Collection containing the ranges to allocate in each individual
* ThreadLocalAccumulator managed by this {@link AccumulatorCompleteRange}
* instance.
*/
private final Collection<LongRange> rangesToAllocate;
/**
* Constructor. Allocates every ThreadLocalAccumulator with an individual
* accumulator for every index contained in the ranges contained by the
* {@link ChunkedList} given as parameter.
* <p>
* Note that subsequent addition of ranges to the {@link ChunkedList} <em>will
* not</em> be reflected into the instance created by calling this constructor.
* If the ranges contained by a {@link ChunkedList} change and this change needs
* to be reflected by the {@link AccumulatorCompleteRange}, a new instance
* should be created.
*
* @param toAllocate {@link ChunkedList} whose contained ranges will be
* allocated for thread-local accumulators prepared by this
* instance
* @param initFunc the function used to allocate the individual allocators
*/
public AccumulatorCompleteRange(ChunkedList<?> toAllocate, Function<Long, A> initFunc) {
this(toAllocate.ranges(), initFunc);
}
/**
* Constructor. Allocates every ThreadLocalAccumulator with an individual
* accumulator for every index contained in the ranges given as parameter.
* <p>
* It is assumed that the ranges given as parameter are mutually exclusive. In
* other words, no two ranges should overlap. Otherwise, exceptions will be
* thrown when using this accumulator.
* <p>
* Also, subsequent modifications to the collection given as parameter will not
* influence the behavior of previously created {@link AccumulatorCompleteRange}
* instance. If a {@link AccumulatorCompleteRange} is desired on a different set
* of ranges, a new instance should be created.
*
* @param ranges the ranges on which this accumulator will be capable of
* accumulating values
*/
public AccumulatorCompleteRange(Collection<LongRange> ranges, Function<Long, A> initFunc) {
super(initFunc);
rangesToAllocate = new ArrayList<>(ranges.size());
rangesToAllocate.addAll(ranges);
}
@Override
protected ThreadLocalAccumulator<A> newThreadLocalAccumulator() {
return new CompleteRangeTLA();
}
}