org.nustaq.offheap.BinaryQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fst Show documentation
Show all versions of fst Show documentation
A fast java serialization drop in-replacement and some serialization based utils such as Structs and OffHeap Memory.
The newest version!
package org.nustaq.offheap;
import org.nustaq.logging.FSTLogger;
import org.nustaq.offheap.bytez.ByteSink;
import org.nustaq.offheap.bytez.ByteSource;
import org.nustaq.offheap.bytez.Bytez;
import org.nustaq.offheap.bytez.onheap.HeapBytez;
/**
* an automatically growing byte queue organized as a ringbuffer.
*
* poll* methods don't throw excpetions but return incomplete or no result instead if
* the queue's content is not sufficient.
* read* methods throw excpetions in case the q contains not enough bytes (need to use available() to
* ensure data is present).
*
* add methods add to the queue. If the adding outperforms reading/polling, the queue is grown automatically.
*
*/
public class BinaryQueue {
private static final FSTLogger logger = FSTLogger.getLogger(BinaryQueue.class);
Bytez storage;
long addIndex = 0;
long pollIndex = 0;
public BinaryQueue() {
this(1024);
}
public BinaryQueue(int qsize) {
storage = new HeapBytez(qsize);
}
/**
* add bytes to the queue. Again by using (reusable) Wrapper classes any kind of memory
* (offheap, byte arrays, nio bytebuffer, memory mapped) can be added.
*
* @param source
*/
public void add(ByteSource source) {
add(source,0, source.length());
}
/**
* add bytes to the queue. Again by using (reusable) Wrapper classes any kind of memory
* (offheap, byte arrays, nio bytebuffer, memory mapped) can be added.
*
* @param source
* @param sourceoff
* @param sourcelen
*/
public void add(ByteSource source, long sourceoff, long sourcelen) {
if ( sourcelen >= remaining() ) {
grow(sourcelen+1); //issue85
add(source,sourceoff,sourcelen);
return;
}
for ( int i=0; i < sourcelen; i++ ) {
storage.put(addIndex++,source.get(i+sourceoff));
if ( addIndex >= storage.length() )
addIndex -= storage.length();
}
}
public void addInt(int written)
{
add((byte) ((written >>> 0) & 0xFF));
add((byte) ((written >>> 8) & 0xFF));
add((byte) ((written >>> 16) & 0xFF));
add((byte) ((written >>> 24) & 0xFF));
}
public void add(byte b) {
long remaining = remaining();
if ( 1 >= remaining) {
grow(1+1); // issue85
add(b);
return;
}
storage.put(addIndex++, b);
if ( addIndex >= storage.length() )
addIndex -= storage.length();
}
protected void grow(long sourcelen) {
HeapBytez newStorage = new HeapBytez((int) Math.max(capacity()*2,capacity()+sourcelen+available()));
long len = poll(newStorage, 0, available());
pollIndex = 0;
addIndex = len;
storage = newStorage;
}
/**
* @return number of bytes free for an add operation
*/
public long remaining() {
return capacity() - available();
}
/**
* read up to destlen bytes (if available).
* Note you can use HeapBytez (implements ByteSink) in order to read to a regular byte array.
* HeapBytez wrapper can be reused to avoid unnecessary allocation.
* Also possible is ByteBufferBasicBytes to read into a ByteBuffer and MallocBytes or MMFBytes to
* read into Unsafe alloc'ed off heap memory or persistent mem mapped memory regions.
*
* @param destination
* @param destoff
* @param destlen
* @return
*/
public long poll(ByteSink destination, long destoff, long destlen) {
long count = 0;
try {
while (pollIndex != addIndex && count < destlen) {
destination.put(destoff + count++, storage.get(pollIndex++));
if (pollIndex >= storage.length()) {
pollIndex = 0;
}
}
} catch (Exception e) {
logger.log(FSTLogger.Level.ERROR, "Failed to poll", e);
}
return count;
}
/**
* convenience method to read len byte array. Throws an excpetion if not enough data is present
*
* @param len
* @return
*/
public byte[] readByteArray(int len) {
if ( available() < len ) {
throw new RuntimeException("not enough data available, check available() > len before calling");
}
byte b[] = new byte[len];
int count = 0;
while ( pollIndex != addIndex && count < len ) {
b[count++] = storage.get(pollIndex++);
if ( pollIndex >= storage.length() ) {
pollIndex = 0;
}
}
return b;
}
/**
* read an int. throws an exception if not enough data is present
* @return
*/
public int readInt() {
if ( available() < 4 ) {
throw new RuntimeException("not enough data available, check available() > 4 before calling");
}
int ch1 = poll();
int ch2 = poll();
int ch3 = poll();
int ch4 = poll();
return (ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0);
}
/**
* @return -1 or the next byte unsigned value
*/
public int poll() {
int result = -1;
if ( pollIndex != addIndex ) {
result = (storage.get(pollIndex++)+256)&0xff;
if ( pollIndex >= storage.length() ) {
pollIndex = 0;
}
}
return result;
}
/**
* 'unread' len bytes
* @param len
*/
public void back( int len ) {
if ( pollIndex >= len )
pollIndex -= len;
else
pollIndex = pollIndex + capacity() - len;
}
/**
* @return number of readable bytes
*/
public long available() {
return addIndex>=pollIndex ? addIndex-pollIndex : addIndex+capacity()-pollIndex;
}
/**
* @return size of underlying ringbuffer
*/
public long capacity() {
return storage.length();
}
@Override
public String toString() {
return "BinaryQueue{" +
"storage=" + storage +
", addIndex=" + addIndex +
", pollIndex=" + pollIndex +
'}';
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy