Use ByteBuf#isAccessible() in more places (#10506)

Motivation

ByteBuf has an isAccessible method which was introduced as part of ref
counting optimizations but there are some places still doing
accessibility checks by accessing the volatile refCnt() directly.

Modifications

- Have PooledNonRetained(Duplicate|Sliced)ByteBuf#isAccessible() use
their refcount delegate's isAccessible() method
- Add static isAccessible(buf) and ensureAccessible(buf) methods to
ByteBufUtil
(since ByteBuf#isAccessible() is package-private)
- Adjust DefaultByteBufHolder and similar classes to use these methods
rather than access refCnt() directly

Result

- More efficient accessibility checks in more places
This commit is contained in:
Nick Hill 2020-08-28 00:18:13 -07:00 committed by GitHub
parent 98c98d53d7
commit 8e8f01e01d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 48 additions and 28 deletions

View File

@ -33,6 +33,10 @@ public abstract class AbstractDerivedByteBuf extends AbstractByteBuf {
@Override
final boolean isAccessible() {
return isAccessible0();
}
boolean isAccessible0() {
return unwrap().isAccessible();
}

View File

@ -16,7 +16,6 @@
package io.netty.buffer;
import io.netty.util.ReferenceCounted;
import io.netty.util.internal.ObjectPool.Handle;
import java.nio.ByteBuffer;
@ -158,13 +157,18 @@ abstract class AbstractPooledDerivedByteBuf extends AbstractReferenceCountedByte
}
private static final class PooledNonRetainedDuplicateByteBuf extends UnpooledDuplicatedByteBuf {
private final ReferenceCounted referenceCountDelegate;
private final ByteBuf referenceCountDelegate;
PooledNonRetainedDuplicateByteBuf(ReferenceCounted referenceCountDelegate, AbstractByteBuf buffer) {
PooledNonRetainedDuplicateByteBuf(ByteBuf referenceCountDelegate, AbstractByteBuf buffer) {
super(buffer);
this.referenceCountDelegate = referenceCountDelegate;
}
@Override
boolean isAccessible0() {
return referenceCountDelegate.isAccessible();
}
@Override
int refCnt0() {
return referenceCountDelegate.refCnt();
@ -234,14 +238,19 @@ abstract class AbstractPooledDerivedByteBuf extends AbstractReferenceCountedByte
}
private static final class PooledNonRetainedSlicedByteBuf extends UnpooledSlicedByteBuf {
private final ReferenceCounted referenceCountDelegate;
private final ByteBuf referenceCountDelegate;
PooledNonRetainedSlicedByteBuf(ReferenceCounted referenceCountDelegate,
PooledNonRetainedSlicedByteBuf(ByteBuf referenceCountDelegate,
AbstractByteBuf buffer, int index, int length) {
super(buffer, index, length);
this.referenceCountDelegate = referenceCountDelegate;
}
@Override
boolean isAccessible0() {
return referenceCountDelegate.isAccessible();
}
@Override
int refCnt0() {
return referenceCountDelegate.refCnt();

View File

@ -18,6 +18,7 @@ package io.netty.buffer;
import io.netty.util.AsciiString;
import io.netty.util.ByteProcessor;
import io.netty.util.CharsetUtil;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.internal.MathUtil;
import io.netty.util.internal.ObjectPool;
@ -108,6 +109,24 @@ public final class ByteBufUtil {
: PlatformDependent.allocateUninitializedArray(minLength);
}
/**
* @return whether the specified buffer has a nonzero ref count
*/
public static boolean isAccessible(ByteBuf buffer) {
return buffer.isAccessible();
}
/**
* @throws IllegalReferenceCountException if the buffer has a zero ref count
* @return the passed in buffer
*/
public static ByteBuf ensureAccessible(ByteBuf buffer) {
if (!buffer.isAccessible()) {
throw new IllegalReferenceCountException(buffer.refCnt());
}
return buffer;
}
/**
* Returns a <a href="http://en.wikipedia.org/wiki/Hex_dump">hex dump</a>
* of the specified buffer's readable bytes.

View File

@ -15,7 +15,6 @@
*/
package io.netty.buffer;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.StringUtil;
@ -33,10 +32,7 @@ public class DefaultByteBufHolder implements ByteBufHolder {
@Override
public ByteBuf content() {
if (data.refCnt() <= 0) {
throw new IllegalReferenceCountException(data.refCnt());
}
return data;
return ByteBufUtil.ensureAccessible(data);
}
/**

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.util.IllegalReferenceCountException;
import static io.netty.util.internal.ObjectUtil.checkNotNull;
@ -152,7 +153,7 @@ public class DefaultFullHttpRequest extends DefaultHttpRequest implements FullHt
public int hashCode() {
int hash = this.hash;
if (hash == 0) {
if (content().refCnt() != 0) {
if (ByteBufUtil.isAccessible(content())) {
try {
hash = 31 + content().hashCode();
} catch (IllegalReferenceCountException ignored) {

View File

@ -16,6 +16,7 @@
package io.netty.handler.codec.http;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.util.IllegalReferenceCountException;
@ -159,7 +160,7 @@ public class DefaultFullHttpResponse extends DefaultHttpResponse implements Full
public int hashCode() {
int hash = this.hash;
if (hash == 0) {
if (content().refCnt() != 0) {
if (ByteBufUtil.isAccessible(content())) {
try {
hash = 31 + content().hashCode();
} catch (IllegalReferenceCountException ignored) {

View File

@ -16,8 +16,8 @@
package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.internal.ObjectUtil;
import io.netty.util.internal.StringUtil;
@ -71,10 +71,7 @@ public class DefaultSpdyDataFrame extends DefaultSpdyStreamFrame implements Spdy
@Override
public ByteBuf content() {
if (data.refCnt() <= 0) {
throw new IllegalReferenceCountException(data.refCnt());
}
return data;
return ByteBufUtil.ensureAccessible(data);
}
@Override

View File

@ -16,8 +16,8 @@
package io.netty.handler.codec.http2;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.util.IllegalReferenceCountException;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.UnstableApi;
@ -104,10 +104,7 @@ public final class DefaultHttp2DataFrame extends AbstractHttp2StreamFrame implem
@Override
public ByteBuf content() {
if (content.refCnt() <= 0) {
throw new IllegalReferenceCountException(content.refCnt());
}
return content;
return ByteBufUtil.ensureAccessible(content);
}
@Override

View File

@ -18,7 +18,7 @@ package io.netty.handler.codec.mqtt;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufHolder;
import io.netty.util.IllegalReferenceCountException;
import io.netty.buffer.ByteBufUtil;
/**
* See <a href="http://public.dhe.ibm.com/software/dw/webservices/ws-mqtt/mqtt-v3r1.html#publish">MQTTV3.1/publish</a>
@ -44,11 +44,7 @@ public class MqttPublishMessage extends MqttMessage implements ByteBufHolder {
@Override
public ByteBuf content() {
final ByteBuf data = (ByteBuf) super.payload();
if (data.refCnt() <= 0) {
throw new IllegalReferenceCountException(data.refCnt());
}
return data;
return ByteBufUtil.ensureAccessible((ByteBuf) super.payload());
}
@Override