[java] ByteBuffers suck, so I wrapped 'em

Started by
-1 comments, last by SteveTaylor 18 years, 2 months ago
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).
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;			
		}
	}
}
[Edited by - SteveTaylor on January 26, 2006 9:23:41 AM]

This topic is closed to new replies.

Advertisement