/** * */ package net.varkhan.base.containers.queue; import net.varkhan.base.containers.Iterator; import java.util.NoSuchElementException; /** * <b>A generic array-backed bounded FIFO queue.</b> * <p/> * This class uses a fixed-size backing array to provide the semantics of a FIFO * queue. Elements are added at the tail of the queue, and are removed from the * head. * <p/> * When the number of elements reaches the size of the backing array, adding an * element triggers the discarding of the head (fist-added) element, as if it * had been normally removed. * <p/> * * @author varkhan * @date Mar 13, 2009 * @time 8:03:07 AM */ public class BoundedBuffer<Type> implements Queue<Type> { /** * The heap array. */ private final Object[] heap; private final int bound; /** * The number of elements in this queue. */ private int size=0; /** * The starting point of the queue in the array. */ private int base=0; /********************************************************************************** ** Constructors **/ /** * Creates a new empty queue with a given capacity. * * @param bound the capacity, and maximum size, of this queue. */ public BoundedBuffer(int bound) { this.bound=bound; this.heap=new Object[bound]; } /********************************************************************************** ** Global information accessors **/ /** * Return the queue size * * @return the number of objects in the queue */ public long size() { return size; } /** * Indicates whether this container is empty. * * @return {@literal true} if this container contains no entry, * {@literal false} otherwise */ public boolean isEmpty() { return size<=0; } /** * Return the maximum queue size * * @return the maximum size of this queue */ public int bound() { return bound; } /** * Removes all objects from the queue */ public final void clear() { size=0; base=0; } /********************************************************************************** ** Queue mechanism **/ /** * Adds an object on the queue. * * @param obj the object to add * * @return {@literal true} */ public final boolean add(Type obj) { if(heap.length==0) return true; int pos=base+size; if(pos<heap.length) { heap[pos]=obj; size++; } else { pos-=heap.length; if(pos==base) base++; else if(pos<base) size++; // This one should never happen: it would mean size>heap.length else { size=heap.length; base=pos+1; } } return true; } /** * Removes and return the smallest object on the queue * * @return the smallest object on the queue */ public final Type poll() { if(size==0) throw new NoSuchElementException(); @SuppressWarnings("unchecked") final Type obj=(Type) heap[base]; heap[base]=null; base++; if(base>=heap.length) base=0; size--; return obj; } /** * Returns, without removing it, the smallest object on the queue * * @return the smallest object on the queue */ @SuppressWarnings("unchecked") public final Type peek() { if(size==0) throw new NoSuchElementException(); return (Type) heap[base]; } /********************************************************************************** ** Iterator operations **/ /** * Returns an element at a given position * * @param pos the position in the queue * * @return the element at position {@code pos} */ @SuppressWarnings("unchecked") public Type get(int pos) { if(pos>=size) throw new ArrayIndexOutOfBoundsException(pos); pos+=base; if(pos<heap.length) return (Type) heap[pos]; else return (Type) heap[pos-heap.length]; } /** * Returns an iterator over the elements of this queue * * @return an Iterator */ public Iterator<Type> iterator() { return new Iterator<Type>() { private int pos=0; public boolean hasNext() { return pos<size; } @SuppressWarnings("unchecked") public Type next() { if(base+pos<heap.length) return (Type) heap[base+pos]; else return (Type) heap[base+pos-heap.length]; } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Iterate over each element of the queue, and pass it as argument to a * visitor's {@link Visitor#invoke(Object, Object)} method, until this method returns * a negative count. * * * @param vis the visitor * @param par the control parameter * * @return the sum of all positive return values from the visitor */ @SuppressWarnings("unchecked") public <Par> long visit(Visitor<Type,Par> vis, Par par) { int pos=0; long c=0; while(pos<size) { Type obj; if(base+pos<heap.length) obj=(Type) heap[base+(pos++)]; else obj=(Type) heap[base+(pos++)-heap.length]; long r=vis.invoke(obj, par); if(r<0) return c; c+=r; } return c; } /** * Returns a string representation of the queue * * @return the string representation of the array of values in the queue */ public String toString() { return net.varkhan.base.containers.array.Arrays.toString(heap); } }