159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.util; 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.Iterator; 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.NoSuchElementException; 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 7a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta * Ring buffer (fixed size queue) implementation using a circular array (array 8a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta * with wrap-around). 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// suppress unchecked warnings in Java 1.5.0_6 and later 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta@SuppressWarnings("unchecked") 12a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Bartapublic class RingBuffer<T> implements Iterable<T> { 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta private T[] buffer; // queue elements 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int count = 0; // number of elements on queue 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int indexOut = 0; // index of first element of queue 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int indexIn = 0; // index of next available slot 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // cast needed since no generic array creation in Java 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public RingBuffer(int capacity) { 21a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta buffer = (T[]) new Object[capacity]; 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean isEmpty() { 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return count == 0; 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int size() { 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return count; 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta public void push(T item) { 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (count == buffer.length) { 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RuntimeException("Ring buffer overflow"); 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta buffer[indexIn] = item; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexIn = (indexIn + 1) % buffer.length; // wrap-around 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count++; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta public T pop() { 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (isEmpty()) { 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new RuntimeException("Ring buffer underflow"); 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta T item = buffer[indexOut]; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta buffer[indexOut] = null; // to help with garbage collection 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count--; 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexOut = (indexOut + 1) % buffer.length; // wrap-around 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return item; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta public Iterator<T> iterator() { 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return new RingBufferIterator(); 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // an iterator, doesn't implement remove() since it's optional 57a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta private class RingBufferIterator implements Iterator<T> { 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int i = 0; 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean hasNext() { 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return i < count; 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void remove() { 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException(); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 69a6b44658eb1c55295f132a36233a11aa2bd8f9cfScott Barta public T next() { 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!hasNext()) { 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new NoSuchElementException(); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return buffer[i++]; 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 77