package cn.anigod.gdwater.turingTool;
import cn.anigod.gdwater.ByteInfo;
import cn.anigod.gdwater.tools.ByteTools;
import cn.anigod.gdwater.tools.FileTools;
import java.util.Date;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class RingBuffer {
int capacity;
volatile int readInd;//最后读到的一位
volatile int writeInd;//最后写到的一位
volatile byte[] data;
Lock lock = new ReentrantLock();
public RingBuffer(int capacity) {
this.capacity = capacity;
this.data = new byte[capacity];
this.readInd = 0;
this.writeInd = 0;
}
public int getCanWriteLen(){
if(readInd == writeInd){
return capacity;
}
if(writeInd > readInd){
return capacity - (writeInd - readInd);
}
if(readInd > writeInd){
return readInd - writeInd;
}
return 0;
}
public int getCanReadLen(){
if(writeInd > readInd){
return writeInd - readInd;
}
if(readInd > writeInd){
return capacity - (readInd - writeInd);
}
return 0;
}
public void clear(){
readInd = 0;
writeInd = 0;
}
public synchronized boolean put(byte[] bs){
lock.lock();
try {
if (bs == null || bs.length == 0) {
lock.unlock();
return false;
}
int writeLen = getCanWriteLen();
while (writeLen >= bs.length) {
break;
}
if (writeInd == readInd) {
if (writeInd == capacity) {
System.arraycopy(bs, 0, data, 0, bs.length);
writeInd = bs.length;
lock.unlock();
return true;
}
int outBorLen = bs.length + writeInd - capacity;
if (outBorLen > 0) {
int inBorLen = capacity - writeInd;
System.arraycopy(bs, 0, data, writeInd, inBorLen);
System.arraycopy(bs, inBorLen, data, 0, outBorLen);
writeInd = outBorLen;
lock.unlock();
return true;
} else {
System.arraycopy(bs, 0, data, writeInd, bs.length);
writeInd = writeInd + bs.length;
lock.unlock();
return true;
}
}
// 写大于读
if (writeInd > readInd) {
int outBorLen = bs.length + writeInd - capacity;
if (outBorLen > 0) {
int inBorLen = capacity - writeInd;
System.arraycopy(bs, 0, data, writeInd, inBorLen);
System.arraycopy(bs, inBorLen, data, 0, outBorLen);
writeInd = outBorLen;
lock.unlock();
return true;
} else {
System.arraycopy(bs, 0, data, writeInd, bs.length);
writeInd = writeInd + bs.length;
lock.unlock();
return true;
}
}
//读大于写
if (readInd > writeInd) {
System.arraycopy(bs, 0, data, writeInd, bs.length);
writeInd = writeInd + bs.length;
lock.unlock();
return true;
}
}catch (Exception e){
System.err.println("writeInd:"+writeInd+", readInd"+readInd+", bsLen:"+bs.length);
}
lock.unlock();
return false;
}
public synchronized byte[] poll(int len){
lock.lock();
if (getCanReadLen() < len) {
lock.unlock();
return null;
}
byte[] temp = new byte[len];
if(writeInd > readInd){
if((writeInd - readInd) < len){
return null;
}
System.arraycopy(data, readInd, temp, 0, len);
readInd = readInd + len;
lock.unlock();
return temp;
}
if(readInd > writeInd){
int outBorLen = len + readInd - capacity;
if(outBorLen > 0){
int inBorLen = capacity - readInd;
System.arraycopy(data, readInd, temp, 0, inBorLen);
System.arraycopy(data, 0, temp, inBorLen, outBorLen);
readInd = outBorLen;
lock.unlock();
return temp;
}
outBorLen = len + readInd - capacity;
if(outBorLen <= 0 ){
int inBorLen = capacity - writeInd;
System.arraycopy(data, readInd, temp, 0, len);
readInd = readInd + len;
lock.unlock();
return temp;
}
}
lock.unlock();
return null;
}
}