Eliminate unnessary wrapping when call ByteBuf.asReadOnly() in some cases

Motivation:

We can eliminate unnessary wrapping when call ByteBuf.asReadOnly() in some cases to reduce indirection.

Modifications:

- Check if asReadOnly() needs to create a new instance or not
- Add test cases

Result:

Less object creation / wrapping.
This commit is contained in:
Norman Maurer 2017-02-13 15:27:40 +01:00
parent adcde84253
commit 371c0ca0f8
4 changed files with 39 additions and 12 deletions

View File

@ -412,4 +412,9 @@ public class ReadOnlyByteBuf extends AbstractDerivedByteBuf {
public ByteBuf capacity(int newCapacity) { public ByteBuf capacity(int newCapacity) {
throw new ReadOnlyBufferException(); throw new ReadOnlyBufferException();
} }
@Override
public ByteBuf asReadOnly() {
return this;
}
} }

View File

@ -26,7 +26,7 @@ final class UnreleasableByteBuf extends WrappedByteBuf {
private SwappedByteBuf swappedBuf; private SwappedByteBuf swappedBuf;
UnreleasableByteBuf(ByteBuf buf) { UnreleasableByteBuf(ByteBuf buf) {
super(buf); super(buf instanceof UnreleasableByteBuf ? buf.unwrap() : buf);
} }
@Override @Override
@ -47,7 +47,7 @@ final class UnreleasableByteBuf extends WrappedByteBuf {
@Override @Override
public ByteBuf asReadOnly() { public ByteBuf asReadOnly() {
return new UnreleasableByteBuf(buf.asReadOnly()); return buf.isReadOnly() ? this : new UnreleasableByteBuf(buf.asReadOnly());
} }
@Override @Override

View File

@ -182,4 +182,13 @@ public class ReadOnlyByteBufTest {
public void shouldIndicteNotWritableAnyNumber() { public void shouldIndicteNotWritableAnyNumber() {
assertFalse(unmodifiableBuffer(buffer(1)).isWritable(1)); assertFalse(unmodifiableBuffer(buffer(1)).isWritable(1));
} }
@Test
public void asReadOnly() {
ByteBuf buf = buffer(1);
ByteBuf readOnly = buf.asReadOnly();
assertTrue(readOnly.isReadOnly());
assertSame(readOnly, readOnly.asReadOnly());
readOnly.release();
}
} }

View File

@ -15,27 +15,40 @@
*/ */
package io.netty.buffer; package io.netty.buffer;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import static io.netty.buffer.Unpooled.buffer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class UnreleaseableByteBufTest { public class UnreleaseableByteBufTest {
@Test @Test
public void testCantRelease() { public void testCantRelease() {
ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copyInt(1)); ByteBuf buf = Unpooled.unreleasableBuffer(Unpooled.copyInt(1));
Assert.assertEquals(1, buf.refCnt()); assertEquals(1, buf.refCnt());
Assert.assertFalse(buf.release()); assertFalse(buf.release());
Assert.assertEquals(1, buf.refCnt()); assertEquals(1, buf.refCnt());
Assert.assertFalse(buf.release()); assertFalse(buf.release());
Assert.assertEquals(1, buf.refCnt()); assertEquals(1, buf.refCnt());
buf.retain(5); buf.retain(5);
Assert.assertEquals(1, buf.refCnt()); assertEquals(1, buf.refCnt());
buf.retain(); buf.retain();
Assert.assertEquals(1, buf.refCnt()); assertEquals(1, buf.refCnt());
Assert.assertTrue(buf.unwrap().release()); assertTrue(buf.unwrap().release());
Assert.assertEquals(0, buf.refCnt()); assertEquals(0, buf.refCnt());
}
@Test
public void testWrappedReadOnly() {
ByteBuf buf = Unpooled.unreleasableBuffer(buffer(1).asReadOnly());
assertSame(buf, buf.asReadOnly());
assertTrue(buf.unwrap().release());
} }
} }