import java.nio.*;
import java.nio.channels.*;
import java.io.*;
public class SocketChannelBuffer
{
public static final int STATE_READ = 1;
public static final int STATE_WRITE = 2;
private ByteBuffer internalBuffer;
private int size;
private int byteCount;
private int state;
public SocketChannelBuffer(int size, boolean direct)
{
this.size = size;
internalBuffer = direct ? ByteBuffer.allocate(size) : ByteBuffer.allocateDirect(size);
byteCount = 0;
state = STATE_READ;
}
public synchronized int put(SocketChannel channel) throws IOException
{
if (byteCount == size)
{
return 0;
}
setRead();
int bytesRead = channel.read(internalBuffer);
// We don't want to update byteCount if bytesRead is -1.
// May as well also catch btyesRead == 0 for efficiency.
if (bytesRead > 0)
{
byteCount += bytesRead;
}
return bytesRead;
}
public synchronized int get(SocketChannel channel) throws IOException
{
if (byteCount == 0)
{
return 0;
}
setWrite();
int bytesWritten = channel.write(internalBuffer);
byteCount -= bytesWritten;
return bytesWritten;
}
public synchronized SocketChannelBuffer put(byte b)
{
if (byteCount == size)
{
throw new BufferOverflowException();
}
setRead();
internalBuffer.put(b);
++byteCount;
return this;
}
public synchronized byte get()
{
if (byteCount == 0)
{
throw new BufferUnderflowException();
}
setWrite();
--byteCount;
return internalBuffer.get();
}
public synchronized SocketChannelBuffer put(byte[] src)
{
if (byteCount + src.length > size)
{
throw new BufferOverflowException();
}
setRead();
internalBuffer.put(src);
byteCount += src.length;
return this;
}
public synchronized SocketChannelBuffer get(byte[] dst)
{
if (byteCount < dst.length)
{
throw new BufferUnderflowException();
}
setWrite();
internalBuffer.get(dst);
byteCount -= dst.length;
return this;
}
private void setRead()
{
switch (state)
{
case STATE_READ:
return;
case STATE_WRITE:
if (byteCount > 0)
{
internalBuffer.compact();
}
else
{
internalBuffer.clear();
}
state = STATE_READ;
}
}
private void setWrite()
{
switch (state)
{
case STATE_READ:
internalBuffer.flip();
state = STATE_WRITE;
return;
case STATE_WRITE:
return;
}
}
}
[java] ByteBuffers suck, so I wrapped 'em
The title is pretty self explanatory. ByteBuffers were giving me too much trouble (at the heart of most of my nio bugs), so I've written a nice wrapper that takes care of their read/write state and makes them thread-safe. This only applies to their usage in SocketChannels. Enjoy :)
EDIT: Fixed errors (eclipse wasn't showing them at first).
[Edited by - SteveTaylor on January 26, 2006 9:23:41 AM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement