commit
35b1d4a4fe
@ -78,11 +78,6 @@ public abstract class BufferHolder<T extends BufferHolder<T>> implements Rc<T> {
|
|||||||
return buf.isOwned();
|
return buf.isOwned();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int countBorrows() {
|
|
||||||
return buf.countBorrows();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Send<T> send() {
|
public Send<T> send() {
|
||||||
|
@ -69,15 +69,6 @@ public interface Rc<I extends Rc<I>> extends AutoCloseable {
|
|||||||
*/
|
*/
|
||||||
boolean isOwned();
|
boolean isOwned();
|
||||||
|
|
||||||
/**
|
|
||||||
* Count the number of borrows of this object.
|
|
||||||
* Note that even if the number of borrows is {@code 0}, this object might not be {@linkplain #isOwned() owned}
|
|
||||||
* because there could be other restrictions involved in ownership.
|
|
||||||
*
|
|
||||||
* @return The number of borrows, if any, of this object.
|
|
||||||
*/
|
|
||||||
int countBorrows();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this object is accessible.
|
* Check if this object is accessible.
|
||||||
*
|
*
|
||||||
|
@ -106,7 +106,13 @@ public abstract class RcSupport<I extends Rc<I>, T extends RcSupport<I, T>> impl
|
|||||||
return acquires == 0;
|
return acquires == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
|
* Count the number of borrows of this object.
|
||||||
|
* Note that even if the number of borrows is {@code 0}, this object might not be {@linkplain #isOwned() owned}
|
||||||
|
* because there could be other restrictions involved in ownership.
|
||||||
|
*
|
||||||
|
* @return The number of borrows, if any, of this object.
|
||||||
|
*/
|
||||||
public int countBorrows() {
|
public int countBorrows() {
|
||||||
return Math.max(acquires, 0);
|
return Math.max(acquires, 0);
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import io.netty.buffer.SlicedByteBuf;
|
|||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import io.netty.buffer.api.Buffer;
|
import io.netty.buffer.api.Buffer;
|
||||||
import io.netty.buffer.api.BufferAllocator;
|
import io.netty.buffer.api.BufferAllocator;
|
||||||
|
import io.netty.buffer.api.RcSupport;
|
||||||
import io.netty.util.ByteProcessor;
|
import io.netty.util.ByteProcessor;
|
||||||
import io.netty.util.IllegalReferenceCountException;
|
import io.netty.util.IllegalReferenceCountException;
|
||||||
|
|
||||||
@ -212,13 +213,13 @@ public final class ByteBufAdaptor extends ByteBuf {
|
|||||||
public ByteBuf ensureWritable(int minWritableBytes) {
|
public ByteBuf ensureWritable(int minWritableBytes) {
|
||||||
checkAccess();
|
checkAccess();
|
||||||
if (writableBytes() < minWritableBytes) {
|
if (writableBytes() < minWritableBytes) {
|
||||||
int borrows = buffer.countBorrows();
|
|
||||||
try {
|
try {
|
||||||
if (borrows == 0) {
|
if (buffer.isOwned()) {
|
||||||
// Good place.
|
// Good place.
|
||||||
buffer.ensureWritable(minWritableBytes);
|
buffer.ensureWritable(minWritableBytes);
|
||||||
} else {
|
} else {
|
||||||
// Highly questionable place, but ByteBuf technically allows this, so we have to emulate.
|
// Highly questionable place, but ByteBuf technically allows this, so we have to emulate.
|
||||||
|
int borrows = countBorrows();
|
||||||
release(borrows);
|
release(borrows);
|
||||||
try {
|
try {
|
||||||
buffer.ensureWritable(minWritableBytes);
|
buffer.ensureWritable(minWritableBytes);
|
||||||
@ -1650,7 +1651,18 @@ public final class ByteBufAdaptor extends ByteBuf {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int refCnt() {
|
public int refCnt() {
|
||||||
return buffer.isAccessible()? 1 + buffer.countBorrows() : 0;
|
return 1 + countBorrows();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countBorrows() {
|
||||||
|
if (!buffer.isAccessible()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (buffer instanceof RcSupport) {
|
||||||
|
var rc = (RcSupport<?, ?>) buffer;
|
||||||
|
return rc.countBorrows();
|
||||||
|
}
|
||||||
|
return buffer.isOwned()? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,7 +163,6 @@ public class BufferReadOnlyTest extends BufferTestSupport {
|
|||||||
assertTrue(buf.isOwned());
|
assertTrue(buf.isOwned());
|
||||||
assertTrue(buf.isAccessible());
|
assertTrue(buf.isAccessible());
|
||||||
assertThat(buf.countComponents()).isOne();
|
assertThat(buf.countComponents()).isOne();
|
||||||
assertThat(buf.countBorrows()).isZero();
|
|
||||||
assertEquals((byte) 1, buf.readByte());
|
assertEquals((byte) 1, buf.readByte());
|
||||||
assertEquals((byte) 2, buf.readByte());
|
assertEquals((byte) 2, buf.readByte());
|
||||||
assertEquals((byte) 3, buf.readByte());
|
assertEquals((byte) 3, buf.readByte());
|
||||||
|
@ -162,12 +162,11 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
void sliceWithoutOffsetAndSizeWillIncreaseReferenceCount(Fixture fixture) {
|
void sliceWithoutOffsetAndSizeWillIncreaseReferenceCount(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
|
||||||
try (Buffer ignored = buf.slice()) {
|
try (Buffer ignored = buf.slice()) {
|
||||||
assertFalse(buf.isOwned());
|
assertFalse(buf.isOwned());
|
||||||
assertThrows(IllegalStateException.class, buf::send);
|
assertThrows(IllegalStateException.class, buf::send);
|
||||||
}
|
}
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,12 +175,11 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
void sliceWithOffsetAndSizeWillIncreaseReferenceCount(Fixture fixture) {
|
void sliceWithOffsetAndSizeWillIncreaseReferenceCount(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
|
||||||
try (Buffer ignored = buf.slice(0, 8)) {
|
try (Buffer ignored = buf.slice(0, 8)) {
|
||||||
assertFalse(buf.isOwned());
|
assertFalse(buf.isOwned());
|
||||||
assertThrows(IllegalStateException.class, buf::send);
|
assertThrows(IllegalStateException.class, buf::send);
|
||||||
}
|
}
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,10 +251,9 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
void sliceWithNegativeOffsetMustThrow(Fixture fixture) {
|
void sliceWithNegativeOffsetMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.slice(-1, 1));
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.slice(-1, 1));
|
||||||
// Verify that the slice is closed properly afterwards.
|
// Verify that the slice is closed properly afterwards.
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,10 +262,9 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
void sliceWithNegativeSizeMustThrow(Fixture fixture) {
|
void sliceWithNegativeSizeMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
|
||||||
assertThrows(IllegalArgumentException.class, () -> buf.slice(0, -1));
|
assertThrows(IllegalArgumentException.class, () -> buf.slice(0, -1));
|
||||||
// Verify that the slice is closed properly afterwards.
|
// Verify that the slice is closed properly afterwards.
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,12 +273,11 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
void sliceWithSizeGreaterThanCapacityMustThrow(Fixture fixture) {
|
void sliceWithSizeGreaterThanCapacityMustThrow(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.slice(0, 9));
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.slice(0, 9));
|
||||||
buf.slice(0, 8).close(); // This is still fine.
|
buf.slice(0, 8).close(); // This is still fine.
|
||||||
assertThrows(IndexOutOfBoundsException.class, () -> buf.slice(1, 8));
|
assertThrows(IndexOutOfBoundsException.class, () -> buf.slice(1, 8));
|
||||||
// Verify that the slice is closed properly afterwards.
|
// Verify that the slice is closed properly afterwards.
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,10 +286,9 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
void sliceWithZeroSizeMustBeAllowed(Fixture fixture) {
|
void sliceWithZeroSizeMustBeAllowed(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
|
||||||
buf.slice(0, 0).close(); // This is fine.
|
buf.slice(0, 0).close(); // This is fine.
|
||||||
// Verify that the slice is closed properly afterwards.
|
// Verify that the slice is closed properly afterwards.
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,24 +297,24 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
public void acquireComposingAndSlicingMustIncrementBorrows(Fixture fixture) {
|
public void acquireComposingAndSlicingMustIncrementBorrows(Fixture fixture) {
|
||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
int borrows = buf.countBorrows();
|
int borrows = countBorrows(buf);
|
||||||
try (Buffer ignored = buf.acquire()) {
|
try (Buffer ignored = buf.acquire()) {
|
||||||
assertEquals(borrows + 1, buf.countBorrows());
|
assertEquals(borrows + 1, countBorrows(buf));
|
||||||
try (Buffer slice = buf.slice()) {
|
try (Buffer slice = buf.slice()) {
|
||||||
assertEquals(0, slice.capacity()); // We haven't written anything, so the slice is empty.
|
assertEquals(0, slice.capacity()); // We haven't written anything, so the slice is empty.
|
||||||
int sliceBorrows = slice.countBorrows();
|
int sliceBorrows = countBorrows(slice);
|
||||||
assertEquals(borrows + 2, buf.countBorrows());
|
assertEquals(borrows + 2, countBorrows(buf));
|
||||||
try (Buffer ignored1 = CompositeBuffer.compose(allocator, buf, slice)) {
|
try (Buffer ignored1 = CompositeBuffer.compose(allocator, buf, slice)) {
|
||||||
assertEquals(borrows + 3, buf.countBorrows());
|
assertEquals(borrows + 3, countBorrows(buf));
|
||||||
// Note: Slice is empty; not acquired by the composite buffer.
|
// Note: Slice is empty; not acquired by the composite buffer.
|
||||||
assertEquals(sliceBorrows, slice.countBorrows());
|
assertEquals(sliceBorrows, countBorrows(slice));
|
||||||
}
|
}
|
||||||
assertEquals(sliceBorrows, slice.countBorrows());
|
assertEquals(sliceBorrows, countBorrows(slice));
|
||||||
assertEquals(borrows + 2, buf.countBorrows());
|
assertEquals(borrows + 2, countBorrows(buf));
|
||||||
}
|
}
|
||||||
assertEquals(borrows + 1, buf.countBorrows());
|
assertEquals(borrows + 1, countBorrows(buf));
|
||||||
}
|
}
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertEquals(borrows, countBorrows(buf));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,23 +324,24 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
|||||||
try (BufferAllocator allocator = fixture.createAllocator();
|
try (BufferAllocator allocator = fixture.createAllocator();
|
||||||
Buffer buf = allocator.allocate(8)) {
|
Buffer buf = allocator.allocate(8)) {
|
||||||
buf.writeByte((byte) 1);
|
buf.writeByte((byte) 1);
|
||||||
int borrows = buf.countBorrows();
|
int borrows = countBorrows(buf);
|
||||||
try (Buffer ignored = buf.acquire()) {
|
try (Buffer ignored = buf.acquire()) {
|
||||||
assertEquals(borrows + 1, buf.countBorrows());
|
assertEquals(borrows + 1, countBorrows(buf));
|
||||||
try (Buffer slice = buf.slice()) {
|
try (Buffer slice = buf.slice()) {
|
||||||
assertEquals(1, slice.capacity());
|
assertEquals(1, slice.capacity());
|
||||||
int sliceBorrows = slice.countBorrows();
|
int sliceBorrows = countBorrows(slice);
|
||||||
assertEquals(borrows + 2, buf.countBorrows());
|
assertEquals(borrows + 2, countBorrows(buf));
|
||||||
try (Buffer ignored1 = CompositeBuffer.compose(allocator, buf, slice)) {
|
try (Buffer ignored1 = CompositeBuffer.compose(allocator, buf, slice)) {
|
||||||
assertEquals(borrows + 3, buf.countBorrows());
|
assertEquals(borrows + 3, countBorrows(buf));
|
||||||
assertEquals(sliceBorrows + 1, slice.countBorrows());
|
assertEquals(sliceBorrows + 1, countBorrows(slice));
|
||||||
}
|
}
|
||||||
assertEquals(sliceBorrows, slice.countBorrows());
|
assertEquals(sliceBorrows, countBorrows(slice));
|
||||||
assertEquals(borrows + 2, buf.countBorrows());
|
assertEquals(borrows + 2, countBorrows(buf));
|
||||||
}
|
}
|
||||||
assertEquals(borrows + 1, buf.countBorrows());
|
assertEquals(borrows + 1, countBorrows(buf));
|
||||||
}
|
}
|
||||||
assertEquals(borrows, buf.countBorrows());
|
assertEquals(borrows, countBorrows(buf));
|
||||||
|
assertTrue(buf.isOwned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -970,6 +970,10 @@ public abstract class BufferTestSupport {
|
|||||||
return bs;
|
return bs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int countBorrows(Buffer buf) {
|
||||||
|
return ((RcSupport<?, ?>) buf).countBorrows();
|
||||||
|
}
|
||||||
|
|
||||||
public static void assertEquals(Buffer expected, Buffer actual) {
|
public static void assertEquals(Buffer expected, Buffer actual) {
|
||||||
assertThat(toByteArray(actual)).containsExactly(toByteArray(expected));
|
assertThat(toByteArray(actual)).containsExactly(toByteArray(expected));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user