zmq.io.coder.EncoderBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jeromq Show documentation
Show all versions of jeromq Show documentation
Pure Java implementation of libzmq
The newest version!
package zmq.io.coder;
import java.nio.ByteBuffer;
import zmq.Msg;
import zmq.util.Errno;
import zmq.util.ValueReference;
public abstract class EncoderBase implements IEncoder
{
// Where to get the data to write from.
private ByteBuffer writeBuf;
// Next step. If set to null, it means that associated data stream
// is dead.
private Runnable next;
// If true, first byte of the message is being written.
private boolean newMsgFlag;
// How much data to write before next step should be executed.
private int toWrite;
// The buffer for encoded data.
private final ByteBuffer buffer;
private final int bufferSize;
private boolean error;
protected Msg inProgress;
private final Errno errno;
protected EncoderBase(Errno errno, int bufferSize)
{
this.errno = errno;
this.bufferSize = bufferSize;
buffer = ByteBuffer.allocateDirect(bufferSize);
error = false;
}
// Load a new message into encoder.
@Override
public final void loadMsg(Msg msg)
{
assert (inProgress == null);
inProgress = msg;
next();
}
// The function returns a batch of binary data. The data
// are filled to a supplied buffer. If no buffer is supplied (data
// is NULL) encoder will provide buffer of its own.
@Override
public final int encode(ValueReference data, int size)
{
int bufferSize = size;
ByteBuffer buf = data.get();
if (buf == null) {
buf = this.buffer;
bufferSize = this.bufferSize;
buffer.clear();
}
if (inProgress == null) {
return 0;
}
int pos = 0;
buf.limit(buf.capacity());
while (pos < bufferSize) {
// If there are no more data to return, run the state machine.
// If there are still no data, return what we already have
// in the buffer.
if (toWrite == 0) {
if (newMsgFlag) {
inProgress = null;
break;
}
next();
}
// If there are no data in the buffer yet and we are able to
// fill whole buffer in a single go, let's use zero-copy.
// There's no disadvantage to it as we cannot stuck multiple
// messages into the buffer anyway. Note that subsequent
// write(s) are non-blocking, thus each single write writes
// at most SO_SNDBUF bytes at once not depending on how large
// is the chunk returned from here.
// As a consequence, large messages being sent won't block
// other engines running in the same I/O thread for excessive
// amounts of time.
if (pos == 0 && data.get() == null && toWrite >= bufferSize) {
writeBuf.limit(writeBuf.capacity());
data.set(writeBuf);
pos = toWrite;
writeBuf = null;
toWrite = 0;
return pos;
}
// Copy data to the buffer. If the buffer is full, return.
int toCopy = Math.min(toWrite, bufferSize - pos);
int limit = writeBuf.limit();
writeBuf.limit(Math.min(writeBuf.capacity(), writeBuf.position() + toCopy));
int current = buf.position();
buf.put(writeBuf);
toCopy = buf.position() - current;
writeBuf.limit(limit);
pos += toCopy;
toWrite -= toCopy;
}
data.set(buf);
return pos;
}
@Override
public void encoded()
{
buffer.flip();
}
protected void encodingError()
{
error = true;
}
public final boolean isError()
{
return error;
}
protected void next()
{
if (next != null) {
next.run();
}
}
protected void nextStep(Msg msg, Runnable state, boolean beginning)
{
if (msg == null) {
nextStep((byte[]) null, 0, state, beginning);
}
else {
nextStep(msg.buf(), state, beginning);
}
}
// This function should be called from derived class to write the data
// to the buffer and schedule next state machine action.
private void nextStep(byte[] buf, int toWrite, Runnable next, boolean newMsgFlag)
{
if (buf != null) {
writeBuf = ByteBuffer.wrap(buf);
writeBuf.limit(toWrite);
}
else {
writeBuf = null;
}
this.toWrite = toWrite;
this.next = next;
this.newMsgFlag = newMsgFlag;
}
protected void initStep(Runnable next, boolean newMsgFlag)
{
nextStep((byte[]) null, 0, next, newMsgFlag);
}
private void nextStep(ByteBuffer buf, Runnable next, boolean newMsgFlag)
{
nextStep(buf, buf.limit(), next, newMsgFlag);
}
protected void nextStep(ByteBuffer buf, int toWrite, Runnable next, boolean newMsgFlag)
{
buf.limit(toWrite);
buf.position(toWrite);
buf.flip();
writeBuf = buf;
this.toWrite = toWrite;
this.next = next;
this.newMsgFlag = newMsgFlag;
}
public int errno()
{
return errno.get();
}
public void errno(int err)
{
this.errno.set(err);
}
@Override
public void destroy()
{
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy