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