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

org.voovan.tools.collection.RingBuffer Maven / Gradle / Ivy

package org.voovan.tools.collection;

import org.voovan.tools.log.Logger;

import java.nio.BufferOverflowException;

/**
 * 无锁环形队列
 *
 * @author: helyho
 * Voovan Framework.
 * WebSite: https://github.com/helyho/Voovan
 * Licence: Apache v2 License
 */
public class RingBuffer {
	public static final int DEFAULT_SIZE = 128;

	public Object[] elements;
	private int readPositon = 0;
	private int writePositon = 0;
	private int size = 0;
	private int capacity;

	/**
	 * 使用默认容量构造一个环形缓冲区
	 */
	public RingBuffer() {
		this(DEFAULT_SIZE);
	}

	/**
	 * 使用指定容量构造一个环形缓冲区
	 *
	 * @param capacity 分配的容量
	 */
	public RingBuffer(int capacity) {
		this.capacity = nextPowerOfTwo(capacity);
		elements = new Object[this.capacity];
	}

	/**
	 * 获得读指针位置
	 *
	 * @return 读指针位置
	 */
	public int getReadPositon() {
		return readPositon;
	}

	/**
	 * 获得写指针位置
	 *
	 * @return 写指针位置
	 */
	public int getWritePositon() {
		return writePositon;
	}

	/**
	 * 获得容量
	 *
	 * @return 容量
	 */
	public int getCapacity() {
		return capacity;
	}

	/**
	 * 读指针跳过特定的偏移量
	 *
	 * @param offset 偏移量
	 */
	public void skip(int offset) {
		if (remaining() < offset || offset < 0) {
			throw new BufferOverflowException();
		}

		readPositon = (readPositon + offset);

		if(readPositon >= capacity)
		readPositon = (readPositon + offset) % capacity;
	}

	/**
	 * 缓冲区空判断
	 *
	 * @return true: 缓冲区无可用数据, false: 缓冲区有可用数据
	 */
	public Boolean isEmpty() {
		return size == 0;
	}

	/**
	 * 缓冲区满判断
	 *
	 * @return true: 缓冲区已满, false: 缓冲区未满
	 */
	public Boolean isFull() {
		return size == capacity;
	}

	/**
	 * 清理缓冲区
	 */
	public void clear() {
		this.readPositon = 0;
		this.writePositon = 0;
	}

	/**
	 * 获得基于索引位置的数据
	 *
	 * @param offset 偏移量
	 * @return byte 数据
	 */
	public T get(int offset) {
		if (offset < remaining()) {
			int realOffset = (readPositon + offset) % capacity;
			return (T)elements[realOffset];
		} else {
			throw new IndexOutOfBoundsException();
		}
	}

	/**
	 * 读取所有缓冲区的数据
	 * 不影响读写位置
	 *
	 * @param t      用于读取数据的 byte 数组
	 * @param offset 偏移量
	 * @param length 数据长度
	 * @return 读取数据大小
	 */
	public int get(T[] t, int offset, int length) {
		if (length > remaining()) {
			length = remaining();
		}

		for (int i = offset; i < offset + length; i++) {
			t[i] = get(i);
		}

		return length;
	}

	/**
	 * 读取所有缓冲区的数据
	 * 不影响读写位置
	 *
	 * @return 读取数据
	 */
	public Object[] toArray() {
		return elements;
	}

	/**
	 * 读取一个 byte
	 *
	 * @return byte 数据
	 */
	public T pop() {
		if (isEmpty()) {
			return null;
		}

		T t = (T)elements[readPositon];

		readPositon = (readPositon + 1);
		readPositon = readPositon == capacity ? 0 : readPositon;
		size--;
		return t;
	}


	/**
	 * 增加一个对象
	 *
	 * @param t 对象
	 * @return true: 成功, false: 失败
	 */
	public boolean push(T t) {
		if (isFull()) {
			return false;
		}

		elements[writePositon] = t;

		writePositon = (writePositon + 1);
		writePositon = writePositon == capacity ? 0 : writePositon;
		size++;
		return true;
	}

	/**
	 * 写入一个 byte[] 数据
	 *
	 * @param ts     T[] 对象
	 * @param offset 针对 byte[] 的偏移量
	 * @param length 写入数据的长度
	 * @return 写入数据长度
	 */
	public int push(T[] ts, int offset, int length) {
		if (length > avaliable()) {
			return 0;
		}

		for (int i = 0; i < length; i++) {
			if(push(ts[offset + i])){
				length = i;
				break;
			}
		}

		return length;
	}

	/**
	 * 缓冲区可用数据量
	 *
	 * @return 缓冲区可用数据量
	 */
	public int remaining() {
		return size;
	}

	/**
	 * 缓冲区可写空间
	 *
	 * @return 缓冲区可写空间
	 */
	public int avaliable() {
		return capacity - size;
	}

	/**
	 * 读取缓冲区的数据
	 *
	 * @param ts     用于读取数据的 byte 数组
	 * @param offset 偏移量
	 * @param length 读取数据的长度
	 * @return 读取数据大小
	 */
	public int pop(T[] ts, int offset, int length) {
		if (length > remaining()) {
			length = remaining();
		}

		for (int i = offset; i < offset + length; i++) {
			ts[i] = pop();
		}

		return length;
	}

	private static int nextPowerOfTwo(int x) {
		if (x == 0) return 1;
		x--;
		x |= x >> 1;
		x |= x >> 2;
		x |= x >> 4;
		x |= x >> 8;
		x |= x >> 16;
		return (x | x >> 32) + 1;
	}

	@Override
	public String toString() {
		return "readPositon=" + readPositon + ", writePositon=" + writePositon + ", capacity=" + capacity + ", remaining=" + remaining() + ", avaliable=" + avaliable();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy