当多线程处理数据的时候,我们需要环形buf用于数据的缓存
public class MyRingBuf {
private static final String TAG = MyRingBuf.class.getSimpleName();
private static final boolean DEBUG_SHOW_ADD = false && com.physicaloid.BuildConfig.DEBUG;
private static final boolean DEBUG_SHOW_GET = false && com.physicaloid.BuildConfig.DEBUG;
private int mRingBufSize;
private byte[] mRingBuf;
private int mAddIndex; // top of data index private int mGetIndex; // tail of data index public long Last_write_time = System.currentTimeMillis();
/** * Ring buffer * @param bufferSize buffer size. It needs enough size e.g.1024 */ public MyRingBuf(int bufferSize) {
mRingBufSize = bufferSize+1;
mRingBuf = new byte[mRingBufSize];
mAddIndex = 0;
mGetIndex = 0;
}
/** * Gets ring buffer size * @return ring buffer size */ public int getRingBufferSize() {
return mRingBufSize-1;
}
/** * Gets buffered length * @return buffered length */ public int getBufferdLength() {
if(mAddIndex >= mGetIndex) {
return mAddIndex - mGetIndex;
} else {
return mAddIndex + (mRingBufSize - mGetIndex);
}
}
/** * Adds byte array to ring buffer * @param buf byte array * @param length added length * @return actually added length */ public synchronized int add(byte[] buf, int length) {
int addLen = length;
if(mAddIndex > mGetIndex) {
if((mAddIndex + length) >= mRingBufSize) { // addした結果1周をまたぐ場合 if((mRingBufSize - mAddIndex) + (mGetIndex - 1) < length ) { // 1周をまたいでなおlength以上になる場合 addLen = (mRingBufSize - mAddIndex) + (mGetIndex-1); // 追い抜かないサイズに修正 }
}
} else if(mAddIndex < mGetIndex){ // 1周をまたいでいる場合 if((mGetIndex - 1) - mAddIndex < length) {
addLen = (mGetIndex - 1) - mAddIndex;
}
}
if(buf.length < addLen) {
addLen = buf.length;
}
if((mAddIndex+addLen) >= mRingBufSize) { // storeがバッファ終端をまたぐ場合 int remain = mAddIndex + addLen - mRingBufSize;
int copyLen = addLen-remain;
if(copyLen != 0) {
System.arraycopy(buf, 0, mRingBuf, mAddIndex, copyLen);
if(DEBUG_SHOW_ADD){ Log.d(TAG, "add(" + length + ") : copy buf[0:" + (copyLen - 1) + "] to mRingBuf[" + mAddIndex + ":" + (mAddIndex + copyLen - 1) + "]"); }
}
mAddIndex = 0;
if(remain != 0) {
System.arraycopy(buf, copyLen, mRingBuf, mAddIndex, remain);
if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : copy buf["+(copyLen)+":"+(addLen-1)+"] to mRingBuf[0:"+(remain-1)+"]"); }
mAddIndex = remain;
}
if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex); }
Last_write_time = System.currentTimeMillis();
return addLen;
} else {
System.arraycopy(buf, 0, mRingBuf, mAddIndex, addLen);
if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : copy buf[0:"+(addLen-1)+"] to mRingBuf["+mAddIndex+":"+(mAddIndex+addLen-1)+"]"); }
mAddIndex += addLen;
if(DEBUG_SHOW_ADD){ Log.d(TAG,"add("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex);}
Last_write_time = System.currentTimeMillis();
return addLen;
}
}
// long click; /** * Gets ring buffer to byte array * @param buf byte array * @param length gotten length * @return actually gotten length */ public synchronized int get(byte[] buf, int length) {
// click = System.currentTimeMillis(); int getLen = length;
if(mAddIndex == mGetIndex) {
return 0;
} else if(mGetIndex < mAddIndex) { // 通常 if(mAddIndex - mGetIndex < length) { // get要求サイズがバッファされているサイズより大きい場合 getLen = mAddIndex - mGetIndex; // 今バッファされているサイズを返す }
} else {// インデックスが1周をまたいでいる場合 if(mAddIndex + (mRingBufSize-mGetIndex) < length) { // get要求サイズがバッファされているサイズより大きい場合 getLen = mAddIndex + (mRingBufSize - mGetIndex); // 今バッファされているサイズを返す }
}
if(buf.length < getLen) {
getLen = buf.length;
}
if((mGetIndex+getLen) >= mRingBufSize) {
int remain = mGetIndex + getLen - mRingBufSize;
int copyLen = getLen - remain;
if( copyLen != 0) {
System.arraycopy(mRingBuf, mGetIndex, buf, 0, copyLen);
if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : copy mRingBuf["+mGetIndex+":"+(mGetIndex+copyLen-1)+"] to buf[0:"+(copyLen-1)+"]"); }
}
mGetIndex = 0;
if(remain !=0) {
System.arraycopy(mRingBuf, mGetIndex, buf, copyLen, remain);
if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : copy mRingBuf[0:"+(remain-1)+"] to buf["+copyLen+":"+(remain-1)+"]"); }
mGetIndex = remain;
}
if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex); }
return getLen;
} else {
System.arraycopy(mRingBuf, mGetIndex, buf, 0, getLen);
if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : copy mRingBuf["+mGetIndex+":"+(mGetIndex+getLen-1)+"] to buf[0:"+(getLen-1)+"]");}
mGetIndex += getLen;
if(DEBUG_SHOW_GET){ Log.d(TAG,"get("+length+") : addOffset = "+mAddIndex+", getOffset = "+mGetIndex); }
return getLen;
}
}
/** * Clear ring buffer */ public synchronized void clear() {
mAddIndex = 0;
mGetIndex = 0;
}
}
使用方法:
读取:
public int read(byte[] buf, int size) {
return mBuffer.get(buf, size);
}
增加:
public int write(byte[] buf, int size) {
if (buf == null) {
return 0;
}
int add = mBuffer.add(buf, size);
return add;
}
写入数据
write(buf, size);
byte[] templ_buf = new byte[2048];
int item_len = read(templ_buf, 4096);
每次读取后会清楚Ringbuf的数据,返回读取的数据长度;