1package com.jme3.util;
2
3import java.util.Iterator;
4import java.util.NoSuchElementException;
5
6/**
7 * Ring buffer (fixed size queue) implementation using a circular array (array
8 * with wrap-around).
9 */
10// suppress unchecked warnings in Java 1.5.0_6 and later
11@SuppressWarnings("unchecked")
12public class RingBuffer<T> implements Iterable<T> {
13
14    private T[] buffer;          // queue elements
15    private int count = 0;          // number of elements on queue
16    private int indexOut = 0;       // index of first element of queue
17    private int indexIn = 0;       // index of next available slot
18
19    // cast needed since no generic array creation in Java
20    public RingBuffer(int capacity) {
21        buffer = (T[]) new Object[capacity];
22    }
23
24    public boolean isEmpty() {
25        return count == 0;
26    }
27
28    public int size() {
29        return count;
30    }
31
32    public void push(T item) {
33        if (count == buffer.length) {
34            throw new RuntimeException("Ring buffer overflow");
35        }
36        buffer[indexIn] = item;
37        indexIn = (indexIn + 1) % buffer.length;     // wrap-around
38        count++;
39    }
40
41    public T pop() {
42        if (isEmpty()) {
43            throw new RuntimeException("Ring buffer underflow");
44        }
45        T item = buffer[indexOut];
46        buffer[indexOut] = null;                  // to help with garbage collection
47        count--;
48        indexOut = (indexOut + 1) % buffer.length; // wrap-around
49        return item;
50    }
51
52    public Iterator<T> iterator() {
53        return new RingBufferIterator();
54    }
55
56    // an iterator, doesn't implement remove() since it's optional
57    private class RingBufferIterator implements Iterator<T> {
58
59        private int i = 0;
60
61        public boolean hasNext() {
62            return i < count;
63        }
64
65        public void remove() {
66            throw new UnsupportedOperationException();
67        }
68
69        public T next() {
70            if (!hasNext()) {
71                throw new NoSuchElementException();
72            }
73            return buffer[i++];
74        }
75    }
76}
77