[#540] Add a variant of ByteBuf.ensureWritableBytes() which does not throw an exception
This commit is contained in:
parent
aa8a761fe2
commit
df0aee22cb
@ -176,17 +176,17 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void ensureWritableBytes(int minWritableBytes) {
|
public void ensureWritableBytes(int minWritableBytes) {
|
||||||
if (minWritableBytes <= writableBytes()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (minWritableBytes < 0) {
|
if (minWritableBytes < 0) {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format(
|
||||||
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
|
"minWritableBytes: %d (expected: >= 0)", minWritableBytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minWritableBytes <= writableBytes()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (minWritableBytes > maxCapacity - writerIndex) {
|
if (minWritableBytes > maxCapacity - writerIndex) {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IndexOutOfBoundsException(String.format(
|
||||||
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d)",
|
"writerIndex(%d) + minWritableBytes(%d) exceeds maxCapacity(%d)",
|
||||||
writerIndex, minWritableBytes, maxCapacity));
|
writerIndex, minWritableBytes, maxCapacity));
|
||||||
}
|
}
|
||||||
@ -198,6 +198,36 @@ public abstract class AbstractByteBuf implements ByteBuf {
|
|||||||
capacity(newCapacity);
|
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) {
|
private int calculateNewCapacity(int minNewCapacity) {
|
||||||
final int maxCapacity = this.maxCapacity;
|
final int maxCapacity = this.maxCapacity;
|
||||||
final int threshold = 1048576 * 4; // 4 MiB page
|
final int threshold = 1048576 * 4; // 4 MiB page
|
||||||
|
@ -443,23 +443,35 @@ public interface ByteBuf extends ChannelBuf, Comparable<ByteBuf> {
|
|||||||
* Makes sure the number of {@linkplain #writableBytes() the writable bytes}
|
* Makes sure the number of {@linkplain #writableBytes() the writable bytes}
|
||||||
* is equal to or greater than the specified value. If there is enough
|
* 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.
|
* writable bytes in this buffer, this method returns with no side effect.
|
||||||
* Otherwise:
|
* Otherwise, it raises an {@link IllegalArgumentException}.
|
||||||
* <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>
|
|
||||||
*
|
*
|
||||||
* @param writableBytes
|
* @param minWritableBytes
|
||||||
* the expected minimum number of writable bytes
|
* the expected minimum number of writable bytes
|
||||||
* @throws IndexOutOfBoundsException
|
* @throws IndexOutOfBoundsException
|
||||||
* if {@linkplain #writableBytes() the writable bytes} of this
|
* if {@link #writerIndex()} + {@code minWritableBytes} > {@link #maxCapacity()}
|
||||||
* buffer is less than the specified value and if this buffer is
|
|
||||||
* not a dynamic buffer
|
|
||||||
*/
|
*/
|
||||||
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.
|
* Gets a boolean at the specified absolute (@code index) in this buffer.
|
||||||
|
@ -172,6 +172,11 @@ public class SwappedByteBuf implements WrappedByteBuf {
|
|||||||
buf.ensureWritableBytes(writableBytes);
|
buf.ensureWritableBytes(writableBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int ensureWritableBytes(int minWritableBytes, boolean force) {
|
||||||
|
return buf.ensureWritableBytes(minWritableBytes, force);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getBoolean(int index) {
|
public boolean getBoolean(int index) {
|
||||||
return buf.getBoolean(index);
|
return buf.getBoolean(index);
|
||||||
|
@ -139,6 +139,11 @@ class ReplayingDecoderBuffer implements ByteBuf {
|
|||||||
throw new UnreplayableOperationException();
|
throw new UnreplayableOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int ensureWritableBytes(int minWritableBytes, boolean force) {
|
||||||
|
throw new UnreplayableOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuf duplicate() {
|
public ByteBuf duplicate() {
|
||||||
throw new UnreplayableOperationException();
|
throw new UnreplayableOperationException();
|
||||||
|
Loading…
Reference in New Issue
Block a user