All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ajjpj.abase.collection.mutable.ARingBuffer Maven / Gradle / Ivy

Go to download

a-base is a library of basic (hence the name) classes, most notably immutable collection classes with copy-on-write operations

There is a newer version: 1.0-pre11
Show newest version
package com.ajjpj.abase.collection.mutable;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Iterator;


/**
 * This is a fixed-size data structure that is optimized for concurrent write performance with less frequent reads. Once
 *  the buffer is full, the least recent elements are overwritten.
 *
 * @author arno
 */
public class ARingBuffer implements Iterable {
    /**
     * This is the number of bins allocated in addition to the nominal buffer size to allow room for buffering write
     *  lag when reading.
     */
    private final Class elementClass;
    private final int bufSize;

    private final T[] buffer;

    /**
     * points to the offset with the first (oldest) element, which is also the next one to be overwritten
     */
    private int next = 0;

    private boolean isFull = false;

    public ARingBuffer(Class cls, int maxSize) {
        elementClass = cls;
        bufSize = maxSize;
        buffer = allocate();
    }

    public synchronized void put(T o) {
        buffer[next] = o;
        next = asBufIndex(next+1);

        if(next == 0) {
            isFull = true;
        }
    }

    public synchronized void clear() {
        next = 0;
        isFull = false;
        Arrays.fill(buffer, null);
    }

    @SuppressWarnings("unchecked")
    private T[] allocate() {
        return (T[]) Array.newInstance(elementClass, bufSize);
    }

    private int asBufIndex(int rawIdx) {
        return (rawIdx + bufSize) % bufSize;
    }

    /**
     * Iterators returned via this method are stable with regard to changes, i.e. changes may occur during iteration,
     *  but they do not affect the elements returned by the iterator.
     */
    @Override public synchronized Iterator iterator() {
        return new Iterator() {
            final T[] snapshot = allocate();

            final int end = next;
            int curPos;
            boolean hasNext;

            {
                System.arraycopy(buffer, 0, snapshot, 0, bufSize);
                curPos = isFull ? next : 0;
                hasNext = isFull || end != 0;
            }

            @Override public boolean hasNext() {
                return hasNext;
            }

            @Override public T next() {
                if(! hasNext) {
                    throw new IndexOutOfBoundsException();
                }

                final T result = snapshot[curPos];
                curPos = asBufIndex(curPos + 1);
                hasNext = curPos != end;
                return result;
            }

            @Override public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy