Little bit of optimization

This commit is contained in:
Trustin Lee 2012-06-01 18:34:19 -07:00
parent e2a617b07b
commit 4440386494
3 changed files with 51 additions and 39 deletions

View File

@ -72,7 +72,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
private final Channel parent; private final Channel parent;
private final Integer id; private final Integer id;
private final Unsafe unsafe; private final Unsafe unsafe;
private final ChannelPipeline pipeline = new DefaultChannelPipeline(this); private final ChannelPipeline pipeline;
private final ChannelFuture succeededFuture = new SucceededChannelFuture(this); private final ChannelFuture succeededFuture = new SucceededChannelFuture(this);
private final ChannelFuture voidFuture = new VoidChannelFuture(this); private final ChannelFuture voidFuture = new VoidChannelFuture(this);
private final CloseFuture closeFuture = new CloseFuture(this); private final CloseFuture closeFuture = new CloseFuture(this);
@ -131,6 +131,8 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
allChannels.remove(id()); allChannels.remove(id());
} }
}); });
pipeline = new DefaultChannelPipeline(this);
} }
@Override @Override
@ -150,6 +152,7 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
@Override @Override
public EventLoop eventLoop() { public EventLoop eventLoop() {
EventLoop eventLoop = this.eventLoop;
if (eventLoop == null) { if (eventLoop == null) {
throw new IllegalStateException("channel not registered to an event loop"); throw new IllegalStateException("channel not registered to an event loop");
} }
@ -581,13 +584,12 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
} }
} }
// Attempt/perform outbound I/O if: if (!inFlushNow) { // Avoid re-entrance
// - the channel is inactive - flush0() will fail the futures.
// - the event loop has no plan to call flushForcibly().
if (!inFlushNow) {
try { try {
if (!isActive() || !isFlushPending()) { if (!isFlushPending()) {
flushNow(); flushNow();
} else {
// Event loop will call flushNow() later by itself.
} }
} catch (Throwable t) { } catch (Throwable t) {
notifyFlushFutures(t); notifyFlushFutures(t);
@ -647,10 +649,6 @@ public abstract class AbstractChannel extends DefaultAttributeMap implements Cha
close(voidFuture()); close(voidFuture());
} }
} }
if (!isActive()) {
close(unsafe().voidFuture());
}
} finally { } finally {
inFlushNow = false; inFlushNow = false;
} }

View File

@ -9,6 +9,7 @@ import java.util.Queue;
final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelInboundHandlerContext<Object>, ChannelOutboundHandlerContext<Object> { final class DefaultChannelHandlerContext extends DefaultAttributeMap implements ChannelInboundHandlerContext<Object>, ChannelOutboundHandlerContext<Object> {
volatile DefaultChannelHandlerContext next; volatile DefaultChannelHandlerContext next;
volatile DefaultChannelHandlerContext prev; volatile DefaultChannelHandlerContext prev;
private final Channel channel;
private final DefaultChannelPipeline pipeline; private final DefaultChannelPipeline pipeline;
final EventExecutor executor; final EventExecutor executor;
private final String name; private final String name;
@ -110,6 +111,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
this.prev = prev; this.prev = prev;
this.next = next; this.next = next;
channel = pipeline.channel;
this.pipeline = pipeline; this.pipeline = pipeline;
this.name = name; this.name = name;
this.handler = handler; this.handler = handler;
@ -153,7 +155,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
@Override @Override
public Channel channel() { public Channel channel() {
return pipeline.channel; return channel;
} }
@Override @Override
@ -164,7 +166,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
@Override @Override
public EventExecutor executor() { public EventExecutor executor() {
if (executor == null) { if (executor == null) {
return channel().eventLoop(); return channel.eventLoop();
} else { } else {
return executor; return executor;
} }
@ -360,16 +362,16 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
@Override @Override
public ChannelFuture newFuture() { public ChannelFuture newFuture() {
return channel().newFuture(); return channel.newFuture();
} }
@Override @Override
public ChannelFuture newSucceededFuture() { public ChannelFuture newSucceededFuture() {
return channel().newSucceededFuture(); return channel.newSucceededFuture();
} }
@Override @Override
public ChannelFuture newFailedFuture(Throwable cause) { public ChannelFuture newFailedFuture(Throwable cause) {
return channel().newFailedFuture(cause); return channel.newFailedFuture(cause);
} }
} }

View File

@ -38,6 +38,9 @@ public class DefaultChannelPipeline implements ChannelPipeline {
static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class); static final InternalLogger logger = InternalLoggerFactory.getInstance(DefaultChannelPipeline.class);
final Channel channel; final Channel channel;
private final Channel.Unsafe unsafe;
private final ChannelBufferHolder<Object> directOutbound;
private volatile DefaultChannelHandlerContext head; private volatile DefaultChannelHandlerContext head;
private volatile DefaultChannelHandlerContext tail; private volatile DefaultChannelHandlerContext tail;
private final Map<String, DefaultChannelHandlerContext> name2ctx = private final Map<String, DefaultChannelHandlerContext> name2ctx =
@ -53,6 +56,8 @@ public class DefaultChannelPipeline implements ChannelPipeline {
throw new NullPointerException("channel"); throw new NullPointerException("channel");
} }
this.channel = channel; this.channel = channel;
unsafe = channel.unsafe();
directOutbound = unsafe.directOutbound();
} }
@Override @Override
@ -667,9 +672,8 @@ public class DefaultChannelPipeline implements ChannelPipeline {
ChannelBuffer nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) { ChannelBuffer nextOutboundByteBuffer(DefaultChannelHandlerContext ctx) {
for (;;) { for (;;) {
if (ctx == null) { if (ctx == null) {
ChannelBufferHolder<Object> lastOut = channel().unsafe().directOutbound(); if (directOutbound.hasByteBuffer()) {
if (lastOut.hasByteBuffer()) { return directOutbound.byteBuffer();
return lastOut.byteBuffer();
} else { } else {
throw NoSuchBufferException.INSTANCE; throw NoSuchBufferException.INSTANCE;
} }
@ -686,9 +690,8 @@ public class DefaultChannelPipeline implements ChannelPipeline {
Queue<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) { Queue<Object> nextOutboundMessageBuffer(DefaultChannelHandlerContext ctx) {
for (;;) { for (;;) {
if (ctx == null) { if (ctx == null) {
ChannelBufferHolder<Object> lastOut = channel().unsafe().directOutbound(); if (directOutbound.hasMessageBuffer()) {
if (lastOut.hasMessageBuffer()) { return directOutbound.messageBuffer();
return lastOut.messageBuffer();
} else { } else {
throw NoSuchBufferException.INSTANCE; throw NoSuchBufferException.INSTANCE;
} }
@ -942,7 +945,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
}); });
} }
} else { } else {
channel().unsafe().bind(localAddress, future); unsafe.bind(localAddress, future);
} }
return future; return future;
} }
@ -980,7 +983,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
}); });
} }
} else { } else {
channel().unsafe().connect(remoteAddress, localAddress, future); unsafe.connect(remoteAddress, localAddress, future);
} }
return future; return future;
@ -1010,7 +1013,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
}); });
} }
} else { } else {
channel().unsafe().disconnect(future); unsafe.disconnect(future);
} }
return future; return future;
@ -1040,7 +1043,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
}); });
} }
} else { } else {
channel().unsafe().close(future); unsafe.close(future);
} }
return future; return future;
@ -1070,7 +1073,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
}); });
} }
} else { } else {
channel().unsafe().deregister(future); unsafe.deregister(future);
} }
return future; return future;
@ -1086,16 +1089,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
if (ctx != null) { if (ctx != null) {
EventExecutor executor = ctx.executor(); EventExecutor executor = ctx.executor();
if (executor.inEventLoop()) { if (executor.inEventLoop()) {
try { flush0(ctx, future);
((ChannelOutboundHandler<Object>) ctx.handler()).flush(ctx, future);
} catch (Throwable t) {
notifyHandlerException(t);
} finally {
ChannelBufferHolder<Object> outbound = ctx.outbound();
if (!outbound.isBypass() && outbound.isEmpty() && outbound.hasByteBuffer()) {
outbound.byteBuffer().discardReadBytes();
}
}
} else { } else {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@Override @Override
@ -1105,12 +1099,25 @@ public class DefaultChannelPipeline implements ChannelPipeline {
}); });
} }
} else { } else {
channel().unsafe().flush(future); unsafe.flush(future);
} }
return future; return future;
} }
private void flush0(final DefaultChannelHandlerContext ctx, ChannelFuture future) {
try {
((ChannelOutboundHandler<Object>) ctx.handler()).flush(ctx, future);
} catch (Throwable t) {
notifyHandlerException(t);
} finally {
ChannelBufferHolder<Object> outbound = ctx.outbound();
if (!outbound.isBypass() && outbound.isEmpty() && outbound.hasByteBuffer()) {
outbound.byteBuffer().discardReadBytes();
}
}
}
@Override @Override
public ChannelFuture write(Object message, ChannelFuture future) { public ChannelFuture write(Object message, ChannelFuture future) {
return write(firstOutboundContext(), message, future); return write(firstOutboundContext(), message, future);
@ -1129,7 +1136,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
out = ctx.outbound(); out = ctx.outbound();
} else { } else {
executor = channel().eventLoop(); executor = channel().eventLoop();
out = channel().unsafe().directOutbound(); out = directOutbound;
} }
if (executor.inEventLoop()) { if (executor.inEventLoop()) {
@ -1143,7 +1150,12 @@ public class DefaultChannelPipeline implements ChannelPipeline {
"cannot write a message whose type is not " + "cannot write a message whose type is not " +
ChannelBuffer.class.getSimpleName() + ": " + message.getClass().getName()); ChannelBuffer.class.getSimpleName() + ": " + message.getClass().getName());
} }
return flush(ctx, future); if (ctx != null) {
flush0(ctx, future);
} else {
unsafe.flush(future);
}
return future;
} else { } else {
executor.execute(new Runnable() { executor.execute(new Runnable() {
@Override @Override