package com.revolsys.parallel.channel.store; import java.util.LinkedList; import java.util.Queue; import com.revolsys.parallel.channel.ChannelValueStore; /** * <h2>Description</h2> * <p> * The Buffer class is an implementation of ChannelValueStore which allows more * than one Object to be sent across the Channel at any one time. The Buffer * will store the Objects and allow them to be read in the same order as they * were written. * </p> * <p> * The getState method will return EMPTY if the Channel does not contain any * Objects, FULL if it cannot accept more data and NONEMPTYFULL otherwise. * </p> * * @author P.D.Austin */ public class Buffer<T> extends ChannelValueStore<T> { /** The storage for the buffered Objects */ private Queue<T> buffer = new LinkedList<>(); private boolean discardIfFull; /** The max size of the Buffer */ private int maxSize; /** * Construct a new Buffer with no maximum size. */ public Buffer() { this(0); } /** * Construct a new Buffer with the specified maximum size. * * @param maxSize The maximum number of Objects the Buffer can store */ public Buffer(final int maxSize) { this(new LinkedList<T>(), maxSize); } /** * Construct a new Buffer with the no maximum size. * * @param buffer The buffer to store the elements in. */ public Buffer(final Queue<T> buffer) { this(buffer, 0); } /** * Construct a new Buffer with the specified maximum size. * * @param buffer The buffer to store the elements in. * @param size The maximum number of Objects the Buffer can store */ public Buffer(final Queue<T> buffer, final int maxSize) { this.buffer = buffer; this.maxSize = maxSize; } /** * Empty the buffer. */ public synchronized void clear() { this.buffer.clear(); } /** * Returns a new Object with the same creation parameters as this Object. This * method should be overridden by subclasses to return a new Object that is * the same type as this Object. The new instance should be created by * constructing a new instance with the same parameters as the original. * <I>NOTE: Only the sizes of the data should be cloned not the stored * data.</I> * * @return The cloned instance of this Object. */ @Override protected Object clone() { return new Buffer<T>(this.maxSize); } /** * Returns the first Object from the Buffer and removes the Object from the * Buffer. * <P> * <I>NOTE: getState should be called before this method to check that the * state is not EMPTY. If the state is EMPTY the Buffer will be left in an * undefined state.</I> * <P> * Pre-condition: The state must not be EMPTY * * @return The next available Object from the Buffer */ @Override protected synchronized T get() { return this.buffer.remove(); } /** * Returns the current state of the Buffer, should be called to ensure the * Pre-conditions of the other methods are not broken. * * @return The current state of the Buffer (EMPTY, NONEMPTYFULL or FULL) */ @Override protected synchronized int getState() { if (this.buffer.isEmpty()) { return EMPTY; } else if (!this.discardIfFull && this.maxSize > 0 && this.buffer.size() == this.maxSize) { return FULL; } else { return NONEMPTYFULL; } } /** * Puts a new Object into the Buffer. * <P> * <I>NOTE: getState should be called before this method to check that the * state is not FULL. If the state is FULL the Buffer will be left in an * undefined state.</I> * <P> * Pre-condition: The state must not be FULL * * @param value The object to put in the Buffer */ @Override protected synchronized void put(final T value) { if (this.maxSize == 0 || this.buffer.size() < this.maxSize) { this.buffer.offer(value); } } /** * Remove the object from the buffer. * * @param object The object to remove. * @return True if the object was removed. */ public boolean remove(final T object) { if (this.buffer.contains(object)) { this.buffer.remove(object); return true; } else { return false; } } /** * The number of items in the buffer. * * @return The number of items in the buffer. */ public int size() { return this.buffer.size(); } @Override public String toString() { return this.buffer.toString(); } }