Rename CodecOutput to RecyclableArrayList and move it to internal package.

* Also reuse it in SslHandler
This commit is contained in:
Norman Maurer 2013-07-10 07:50:26 +02:00
parent 768152cf88
commit da5c6add14
7 changed files with 42 additions and 35 deletions

View File

@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.internal.RecyclableArrayList;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
import java.util.List; import java.util.List;
@ -120,7 +121,7 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
@Override @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
CodecOutput out = CodecOutput.newInstance(); RecyclableArrayList out = RecyclableArrayList.newInstance();
try { try {
if (msg instanceof ByteBuf) { if (msg instanceof ByteBuf) {
ByteBuf data = (ByteBuf) msg; ByteBuf data = (ByteBuf) msg;
@ -189,7 +190,7 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { public void channelInactive(ChannelHandlerContext ctx) throws Exception {
CodecOutput out = CodecOutput.newInstance(); RecyclableArrayList out = RecyclableArrayList.newInstance();
try { try {
if (cumulation != null) { if (cumulation != null) {
callDecode(ctx, cumulation, out); callDecode(ctx, cumulation, out);
@ -214,7 +215,7 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
} }
} }
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, CodecOutput out) { protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, RecyclableArrayList out) {
try { try {
while (in.isReadable()) { while (in.isReadable()) {
int outSize = out.size(); int outSize = out.size();
@ -252,7 +253,7 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
* *
* @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
* @param in the {@link ByteBuf} from which to read data * @param in the {@link ByteBuf} from which to read data
* @param out the {@link CodecOutput} to which decoded messages should be added * @param out the {@link List} to which decoded messages should be added
* @throws Exception is thrown if an error accour * @throws Exception is thrown if an error accour
*/ */

View File

@ -105,8 +105,8 @@ public abstract class MessageToByteEncoder<I> extends ChannelOutboundHandlerAdap
} }
/** /**
* Encode a message into a {@link ByteBuf}. This method will be called till the {@link CodecOutput} has * Encode a message into a {@link ByteBuf}. This method will be called for each written message that can be handled
* nothing left. * by this encoder.
* *
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToByteEncoder} belongs to
* @param msg the message to encode * @param msg the message to encode

View File

@ -19,6 +19,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import io.netty.util.ReferenceCounted; import io.netty.util.ReferenceCounted;
import io.netty.util.internal.RecyclableArrayList;
import io.netty.util.internal.TypeParameterMatcher; import io.netty.util.internal.TypeParameterMatcher;
import java.util.List; import java.util.List;
@ -65,7 +66,7 @@ public abstract class MessageToMessageDecoder<I> extends ChannelInboundHandlerAd
@Override @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
CodecOutput out = CodecOutput.newInstance(); RecyclableArrayList out = RecyclableArrayList.newInstance();
try { try {
if (acceptInboundMessage(msg)) { if (acceptInboundMessage(msg)) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -91,12 +92,12 @@ public abstract class MessageToMessageDecoder<I> extends ChannelInboundHandlerAd
} }
/** /**
* Decode from one message to an other. This method will be called till either the {@link CodecOutput} has * Decode from one message to an other. This method will be called for each written message that can be handled
* nothing left or till this method returns {@code null}. * by this encoder.
* *
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageDecoder} belongs to * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageDecoder} belongs to
* @param msg the message to decode to an other one * @param msg the message to decode to an other one
* @param out the {@link CodecOutput} to which decoded messages should be added * @param out the {@link List} to which decoded messages should be added
* @throws Exception is thrown if an error accour * @throws Exception is thrown if an error accour
*/ */
protected abstract void decode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception; protected abstract void decode(ChannelHandlerContext ctx, I msg, List<Object> out) throws Exception;

View File

@ -19,6 +19,7 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter; import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil; import io.netty.util.ReferenceCountUtil;
import io.netty.util.ReferenceCounted; import io.netty.util.ReferenceCounted;
import io.netty.util.internal.RecyclableArrayList;
import io.netty.util.internal.TypeParameterMatcher; import io.netty.util.internal.TypeParameterMatcher;
import java.util.List; import java.util.List;
@ -62,7 +63,7 @@ public abstract class MessageToMessageEncoder<I> extends ChannelOutboundHandlerA
@Override @Override
public void write(ChannelHandlerContext ctx, Object msg) throws Exception { public void write(ChannelHandlerContext ctx, Object msg) throws Exception {
CodecOutput out = CodecOutput.newInstance(); RecyclableArrayList out = RecyclableArrayList.newInstance();
try { try {
if (acceptOutboundMessage(msg)) { if (acceptOutboundMessage(msg)) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -88,12 +89,12 @@ public abstract class MessageToMessageEncoder<I> extends ChannelOutboundHandlerA
} }
/** /**
* Encode from one message to an other. This method will be called till either the {@link CodecOutput} has nothing * Encode from one message to an other. This method will be called for each written message that can be handled
* left or till this method returns {@code null}. * by this encoder.
* *
* @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageEncoder} belongs to * @param ctx the {@link ChannelHandlerContext} which this {@link MessageToMessageEncoder} belongs to
* @param msg the message to encode to an other one * @param msg the message to encode to an other one
* @param out the {@link CodecOutput} into which the encoded msg should be added * @param out the {@link List} into which the encoded msg should be added
* needs to do some kind of aggragation * needs to do some kind of aggragation
* @throws Exception is thrown if an error accour * @throws Exception is thrown if an error accour
*/ */

View File

@ -20,6 +20,7 @@ import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.util.Signal; import io.netty.util.Signal;
import io.netty.util.internal.RecyclableArrayList;
import io.netty.util.internal.StringUtil; import io.netty.util.internal.StringUtil;
/** /**
@ -319,7 +320,7 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
@Override @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception { public void channelInactive(ChannelHandlerContext ctx) throws Exception {
CodecOutput out = CodecOutput.newInstance(); RecyclableArrayList out = RecyclableArrayList.newInstance();
try { try {
replayable.terminate(); replayable.terminate();
callDecode(ctx, internalBuffer(), out); callDecode(ctx, internalBuffer(), out);
@ -345,7 +346,7 @@ public abstract class ReplayingDecoder<S> extends ByteToMessageDecoder {
} }
@Override @Override
protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, CodecOutput out) { protected void callDecode(ChannelHandlerContext ctx, ByteBuf in, RecyclableArrayList out) {
replayable.setCumulation(in); replayable.setCumulation(in);
try { try {
while (in.isReadable()) { while (in.isReadable()) {

View File

@ -14,7 +14,7 @@
* under the License. * under the License.
*/ */
package io.netty.handler.codec; package io.netty.util.internal;
import io.netty.util.Recycler; import io.netty.util.Recycler;
import io.netty.util.Recycler.Handle; import io.netty.util.Recycler.Handle;
@ -24,42 +24,42 @@ import java.util.ArrayList;
/** /**
* A simple list that holds the output of a codec. * A simple list that holds the output of a codec.
*/ */
final class CodecOutput extends ArrayList<Object> { public final class RecyclableArrayList extends ArrayList<Object> {
private static final long serialVersionUID = -8605125654176467947L; private static final long serialVersionUID = -8605125654176467947L;
private static final int DEFAULT_INITIAL_CAPACITY = 8; private static final int DEFAULT_INITIAL_CAPACITY = 8;
private static final Recycler<CodecOutput> RECYCLER = new Recycler<CodecOutput>() { private static final Recycler<RecyclableArrayList> RECYCLER = new Recycler<RecyclableArrayList>() {
@Override @Override
protected CodecOutput newObject(Handle handle) { protected RecyclableArrayList newObject(Handle handle) {
return new CodecOutput(handle); return new RecyclableArrayList(handle);
} }
}; };
/** /**
* Create a new empty {@link CodecOutput} instance * Create a new empty {@link RecyclableArrayList} instance
*/ */
public static CodecOutput newInstance() { public static RecyclableArrayList newInstance() {
return newInstance(DEFAULT_INITIAL_CAPACITY); return newInstance(DEFAULT_INITIAL_CAPACITY);
} }
/** /**
* Create a new empty {@link CodecOutput} instance with the given capacity. * Create a new empty {@link RecyclableArrayList} instance with the given capacity.
*/ */
public static CodecOutput newInstance(int minCapacity) { public static RecyclableArrayList newInstance(int minCapacity) {
CodecOutput ret = (CodecOutput) RECYCLER.get(); RecyclableArrayList ret = RECYCLER.get();
ret.ensureCapacity(minCapacity); ret.ensureCapacity(minCapacity);
return ret; return ret;
} }
private final Handle handle; private final Handle handle;
CodecOutput(Handle handle) { private RecyclableArrayList(Handle handle) {
this(handle, DEFAULT_INITIAL_CAPACITY); this(handle, DEFAULT_INITIAL_CAPACITY);
} }
CodecOutput(Handle handle, int initialCapacity) { private RecyclableArrayList(Handle handle, int initialCapacity) {
super(initialCapacity); super(initialCapacity);
this.handle = handle; this.handle = handle;
} }
@ -67,7 +67,7 @@ final class CodecOutput extends ArrayList<Object> {
/** /**
* Clear and recycle this instance. * Clear and recycle this instance.
*/ */
boolean recycle() { public boolean recycle() {
clear(); clear();
return RECYCLER.recycle(this, handle); return RECYCLER.recycle(this, handle);
} }

View File

@ -36,6 +36,7 @@ import io.netty.util.concurrent.GenericFutureListener;
import io.netty.util.concurrent.ImmediateExecutor; import io.netty.util.concurrent.ImmediateExecutor;
import io.netty.util.internal.EmptyArrays; import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.RecyclableArrayList;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
@ -50,7 +51,6 @@ import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel; import java.nio.channels.DatagramChannel;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque; import java.util.Deque;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -536,11 +536,14 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
} }
private void unwrapLater(ChannelHandlerContext ctx) throws SSLException { private void unwrapLater(ChannelHandlerContext ctx) throws SSLException {
// TODO: Optimize this for less Garbage RecyclableArrayList out = RecyclableArrayList.newInstance();
List<Object> messageList = new ArrayList<Object>(); try {
decode(ctx, internalBuffer(), messageList); decode(ctx, internalBuffer(), out);
for (int i = 0; i < messageList.size(); i++) { for (int i = 0; i < out.size(); i++) {
ctx.fireChannelRead(messageList.get(i)); ctx.fireChannelRead(out.get(i));
}
} finally {
out.recycle();
} }
} }