[#540] Add a variant of ByteBuf.ensureWritableBytes() which does not throw an exception

This commit is contained in:
Trustin Lee 2012-08-20 12:52:38 +09:00
parent aa8a761fe2
commit df0aee22cb
4 changed files with 70 additions and 18 deletions

View File

@ -176,17 +176,17 @@ public abstract class AbstractByteBuf implements ByteBuf {
@Override
public void ensureWritableBytes(int minWritableBytes) {
if (minWritableBytes <= writableBytes()) {
return;
}
if (minWritableBytes < 0) {
throw new IllegalArgumentException(String.format(
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
}
if (minWritableBytes <= writableBytes()) {
return;
}
if (minWritableBytes > maxCapacity - writerIndex) {
throw new IllegalArgumentException(String.format(
throw new IndexOutOfBoundsException(String.format(
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d)",
writerIndex, minWritableBytes, maxCapacity));
}
@ -198,6 +198,36 @@ public abstract class AbstractByteBuf implements ByteBuf {
capacity(newCapacity);
}
@Override
public int ensureWritableBytes(int minWritableBytes, boolean force) {
if (minWritableBytes < 0) {
throw new IllegalArgumentException(String.format(
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
}
if (minWritableBytes <= writableBytes()) {
return 0;
}
if (minWritableBytes > maxCapacity - writerIndex) {
if (force) {
if (capacity() == maxCapacity()) {
return 1;
}
capacity(maxCapacity());
return 3;
}
}
// Normalize the current capacity to the power of 2.
int newCapacity = calculateNewCapacity(writerIndex + minWritableBytes);
// Adjust to the new capacity.
capacity(newCapacity);
return 2;
}
private int calculateNewCapacity(int minNewCapacity) {
final int maxCapacity = this.maxCapacity;
final int threshold = 1048576 * 4; // 4 MiB page

View File

@ -443,23 +443,35 @@ public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
* Makes sure the number of {@linkplain #writableBytes() the writable bytes}
* is equal to or greater than the specified value. If there is enough
* writable bytes in this buffer, this method returns with no side effect.
* Otherwise:
* <ul>
* <li>a non-dynamic buffer will throw an {@link IndexOutOfBoundsException}.</li>
* <li>a dynamic buffer will expand its capacity so that the number of the
* {@link #writableBytes() writable bytes} becomes equal to or greater
* than the specified value. The expansion involves the reallocation of
* the internal buffer and consequently memory copy.</li>
* </ul>
* Otherwise, it raises an {@link IllegalArgumentException}.
*
* @param writableBytes
* @param minWritableBytes
* the expected minimum number of writable bytes
* @throws IndexOutOfBoundsException
* if {@linkplain #writableBytes() the writable bytes} of this
* buffer is less than the specified value and if this buffer is
* not a dynamic buffer
* if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}
*/
void ensureWritableBytes(int writableBytes);
void ensureWritableBytes(int minWritableBytes);
/**
* Tries to make sure the number of {@linkplain #writableBytes() the writable bytes}
* is equal to or greater than the specified value. Unlike {@link #ensureWritableBytes(int)},
* this method does not raise an exception but returns a code.
*
* @param minWritableBytes
* the expected minimum number of writable bytes
* @param force
* When {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}:
* <ul>
* <li>{@code true} - the capacity of the buffer is expanded to {@link #maxCapacity()}</li>
* <li>{@code false} - the capacity of the buffer is unchanged</li>
* </ul>
* @return {@code 0} if the buffer has enough writable bytes, and its capacity is unchanged.
* {@code 1} if the buffer does not have enough bytes, and its capacity is unchanged.
* {@code 2} if the buffer has enough writable bytes, and its capacity has been increased.
* {@code 3} if the buffer does not have enough bytes, but its capacity has been
* increased to its maximum.
*/
int ensureWritableBytes(int minWritableBytes, boolean force);
/**
* Gets a boolean at the specified absolute (@code index) in this buffer.

View File

@ -172,6 +172,11 @@ public class SwappedByteBuf implements WrappedByteBuf {
buf.ensureWritableBytes(writableBytes);
}
@Override
public int ensureWritableBytes(int minWritableBytes, boolean force) {
return buf.ensureWritableBytes(minWritableBytes, force);
}
@Override
public boolean getBoolean(int index) {
return buf.getBoolean(index);

View File

@ -139,6 +139,11 @@ class ReplayingDecoderBuffer implements ByteBuf {
throw new UnreplayableOperationException();
}
@Override
public int ensureWritableBytes(int minWritableBytes, boolean force) {
throw new UnreplayableOperationException();
}
@Override
public ByteBuf duplicate() {
throw new UnreplayableOperationException();