| package com.jme3.util; |
| |
| import java.util.Iterator; |
| import java.util.NoSuchElementException; |
| |
| /** |
| * Ring buffer (fixed size queue) implementation using a circular array (array |
| * with wrap-around). |
| */ |
| // suppress unchecked warnings in Java 1.5.0_6 and later |
| @SuppressWarnings("unchecked") |
| public class RingBuffer<T> implements Iterable<T> { |
| |
| private T[] buffer; // queue elements |
| private int count = 0; // number of elements on queue |
| private int indexOut = 0; // index of first element of queue |
| private int indexIn = 0; // index of next available slot |
| |
| // cast needed since no generic array creation in Java |
| public RingBuffer(int capacity) { |
| buffer = (T[]) new Object[capacity]; |
| } |
| |
| public boolean isEmpty() { |
| return count == 0; |
| } |
| |
| public int size() { |
| return count; |
| } |
| |
| public void push(T item) { |
| if (count == buffer.length) { |
| throw new RuntimeException("Ring buffer overflow"); |
| } |
| buffer[indexIn] = item; |
| indexIn = (indexIn + 1) % buffer.length; // wrap-around |
| count++; |
| } |
| |
| public T pop() { |
| if (isEmpty()) { |
| throw new RuntimeException("Ring buffer underflow"); |
| } |
| T item = buffer[indexOut]; |
| buffer[indexOut] = null; // to help with garbage collection |
| count--; |
| indexOut = (indexOut + 1) % buffer.length; // wrap-around |
| return item; |
| } |
| |
| public Iterator<T> iterator() { |
| return new RingBufferIterator(); |
| } |
| |
| // an iterator, doesn't implement remove() since it's optional |
| private class RingBufferIterator implements Iterator<T> { |
| |
| private int i = 0; |
| |
| public boolean hasNext() { |
| return i < count; |
| } |
| |
| public void remove() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| public T next() { |
| if (!hasNext()) { |
| throw new NoSuchElementException(); |
| } |
| return buffer[i++]; |
| } |
| } |
| } |