Reduce object allocation by using same ChannelFutureListener instance.

Motivation:

When VoidChannelPromise.unvoid() was called we created a new ChannelFutureListener everytime. This is not needed as its stateless.

Modifications:

Reuse the ChannelFutureListener.

Result:

Less object allocations
This commit is contained in:
Norman Maurer 2018-01-25 10:07:26 +01:00
parent 4afabd3f3c
commit 36304e1f05

View File

@ -26,19 +26,32 @@ import java.util.concurrent.TimeUnit;
public final class VoidChannelPromise extends AbstractFuture<Void> implements ChannelPromise {
private final Channel channel;
private final boolean fireException;
// Will be null if we should not propagate exceptions through the pipeline on failure case.
private final ChannelFutureListener fireExceptionListener;
/**
* Creates a new instance.
*
* @param channel the {@link Channel} associated with this future
*/
public VoidChannelPromise(Channel channel, boolean fireException) {
public VoidChannelPromise(final Channel channel, boolean fireException) {
if (channel == null) {
throw new NullPointerException("channel");
}
this.channel = channel;
this.fireException = fireException;
if (fireException) {
fireExceptionListener = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
Throwable cause = future.cause();
if (cause != null) {
fireException0(cause);
}
}
};
} else {
fireExceptionListener = null;
}
}
@Override
@ -151,7 +164,7 @@ public final class VoidChannelPromise extends AbstractFuture<Void> implements Ch
}
@Override
public VoidChannelPromise setFailure(Throwable cause) {
fireException(cause);
fireException0(cause);
return this;
}
@ -162,7 +175,7 @@ public final class VoidChannelPromise extends AbstractFuture<Void> implements Ch
@Override
public boolean tryFailure(Throwable cause) {
fireException(cause);
fireException0(cause);
return false;
}
@ -198,15 +211,8 @@ public final class VoidChannelPromise extends AbstractFuture<Void> implements Ch
@Override
public ChannelPromise unvoid() {
ChannelPromise promise = new DefaultChannelPromise(channel);
if (fireException) {
promise.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
fireException(future.cause());
}
}
});
if (fireExceptionListener != null) {
promise.addListener(fireExceptionListener);
}
return promise;
}
@ -216,12 +222,12 @@ public final class VoidChannelPromise extends AbstractFuture<Void> implements Ch
return true;
}
private void fireException(Throwable cause) {
private void fireException0(Throwable cause) {
// Only fire the exception if the channel is open and registered
// if not the pipeline is not setup and so it would hit the tail
// of the pipeline.
// See https://github.com/netty/netty/issues/1517
if (fireException && channel.isRegistered()) {
if (fireExceptionListener != null && channel.isRegistered()) {
channel.pipeline().fireExceptionCaught(cause);
}
}