Address @trustin 's comments and also make sure the accept of AIO is only triggered from the event loop. See #71

This commit is contained in:
norman 2012-07-31 11:42:29 +02:00
parent 8b473dce6c
commit 16a4088344
18 changed files with 77 additions and 72 deletions

View File

@ -23,5 +23,4 @@ public interface ChannelStateHandler extends ChannelHandler {
void channelInactive(ChannelHandlerContext ctx) throws Exception; void channelInactive(ChannelHandlerContext ctx) throws Exception;
void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception; void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception;
} }

View File

@ -63,7 +63,7 @@ final class DefaultChannelHandlerContext extends DefaultAttributeMap implements
final AtomicReference<ByteBridge> inByteBridge; final AtomicReference<ByteBridge> inByteBridge;
final AtomicReference<ByteBridge> outByteBridge; final AtomicReference<ByteBridge> outByteBridge;
final AtomicBoolean suspendRead = new AtomicBoolean(false); final AtomicBoolean suspendRead = new AtomicBoolean();
// Runnables that calls handlers // Runnables that calls handlers
final Runnable fireChannelRegisteredTask = new Runnable() { final Runnable fireChannelRegisteredTask = new Runnable() {

View File

@ -467,7 +467,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
callAfterRemove(ctx); callAfterRemove(ctx);
// make sure we clear the readable flag // make sure the it's set back to readable
ctx.readable(true); ctx.readable(true);
} }
@ -529,11 +529,8 @@ public class DefaultChannelPipeline implements ChannelPipeline {
callBeforeRemove(oldTail); callBeforeRemove(oldTail);
// clear readable suspend if necessary // make sure the it's set back to readable
oldTail.readable(true); oldTail.readable(true);
} }
@Override @Override

View File

@ -86,7 +86,7 @@ abstract class AbstractAioChannel extends AbstractChannel {
return loop instanceof AioChildEventLoop; return loop instanceof AioChildEventLoop;
} }
protected abstract class AsyncUnsafe extends AbstractUnsafe { protected abstract class AbstractAioUnsafe extends AbstractUnsafe {
@Override @Override
public void connect(final SocketAddress remoteAddress, public void connect(final SocketAddress remoteAddress,

View File

@ -42,7 +42,15 @@ public class AioServerSocketChannel extends AbstractAioChannel implements Server
private final AioServerSocketChannelConfig config; private final AioServerSocketChannelConfig config;
private boolean closed; private boolean closed;
private AtomicBoolean readSuspend = new AtomicBoolean(); private AtomicBoolean readSuspended = new AtomicBoolean();
private final Runnable acceptTask = new Runnable() {
@Override
public void run() {
doAccept();
}
};
private static AsynchronousServerSocketChannel newSocket(AsynchronousChannelGroup group) { private static AsynchronousServerSocketChannel newSocket(AsynchronousChannelGroup group) {
try { try {
@ -94,7 +102,7 @@ public class AioServerSocketChannel extends AbstractAioChannel implements Server
} }
private void doAccept() { private void doAccept() {
if (readSuspend.get()) { if (readSuspended.get()) {
return; return;
} }
javaChannel().accept(this, ACCEPT_HANDLER); javaChannel().accept(this, ACCEPT_HANDLER);
@ -140,7 +148,7 @@ public class AioServerSocketChannel extends AbstractAioChannel implements Server
// create the socket add it to the buffer and fire the event // create the socket add it to the buffer and fire the event
channel.pipeline().inboundMessageBuffer().add( channel.pipeline().inboundMessageBuffer().add(
new AioSocketChannel(channel, null, channel.eventLoop, ch)); new AioSocketChannel(channel, null, channel.eventLoop, ch));
if (!channel.readSuspend.get()) { if (!channel.readSuspended.get()) {
channel.pipeline().fireInboundBufferUpdated(); channel.pipeline().fireInboundBufferUpdated();
} }
} }
@ -167,19 +175,25 @@ public class AioServerSocketChannel extends AbstractAioChannel implements Server
@Override @Override
protected Unsafe newUnsafe() { protected Unsafe newUnsafe() {
return new AsyncUnsafe() { return new AioServerSocketUnsafe();
}
@Override private final class AioServerSocketUnsafe extends AbstractAioUnsafe {
public void suspendRead() {
readSuspend.set(true);
}
@Override @Override
public void resumeRead() { public void suspendRead() {
if (readSuspend.compareAndSet(true, false)) { readSuspended.set(true);
}
@Override
public void resumeRead() {
if (readSuspended.compareAndSet(true, false)) {
if (eventLoop().inEventLoop()) {
doAccept(); doAccept();
} else {
eventLoop().execute(acceptTask);
} }
} }
}; }
} }
} }

View File

@ -53,7 +53,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
private final AioSocketChannelConfig config; private final AioSocketChannelConfig config;
private boolean flushing; private boolean flushing;
private final AtomicBoolean readSuspend = new AtomicBoolean(false); private final AtomicBoolean readSuspended = new AtomicBoolean();
private final Runnable readTask = new Runnable() { private final Runnable readTask = new Runnable() {
@Override @Override
@ -187,7 +187,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
} }
private void beginRead() { private void beginRead() {
if (readSuspend.get()) { if (readSuspended.get()) {
return; return;
} }
@ -284,7 +284,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
} catch (Throwable t) { } catch (Throwable t) {
if (read) { if (read) {
read = false; read = false;
if (!channel.readSuspend.get()) { if (!channel.readSuspended.get()) {
pipeline.fireInboundBufferUpdated(); pipeline.fireInboundBufferUpdated();
} }
} }
@ -298,7 +298,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
} }
} finally { } finally {
if (read) { if (read) {
if (!channel.readSuspend.get()) { if (!channel.readSuspended.get()) {
pipeline.fireInboundBufferUpdated(); pipeline.fireInboundBufferUpdated();
} }
} }
@ -333,13 +333,13 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
@Override @Override
protected void completed0(Void result, AioSocketChannel channel) { protected void completed0(Void result, AioSocketChannel channel) {
channel.beginRead(); channel.beginRead();
((AsyncUnsafe) channel.unsafe()).connectSuccess(); ((AbstractAioUnsafe) channel.unsafe()).connectSuccess();
channel.pipeline().fireChannelActive(); channel.pipeline().fireChannelActive();
} }
@Override @Override
protected void failed0(Throwable exc, AioSocketChannel channel) { protected void failed0(Throwable exc, AioSocketChannel channel) {
((AsyncUnsafe) channel.unsafe()).connectFailed(exc); ((AbstractAioUnsafe) channel.unsafe()).connectFailed(exc);
} }
} }
@ -353,16 +353,16 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
return new AioSocketChannelAsyncUnsafe(); return new AioSocketChannelAsyncUnsafe();
} }
private final class AioSocketChannelAsyncUnsafe extends AsyncUnsafe { private final class AioSocketChannelAsyncUnsafe extends AbstractAioUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {
readSuspend.set(true); readSuspended.set(true);
} }
@Override @Override
public void resumeRead() { public void resumeRead() {
if (readSuspend.compareAndSet(true, false)) { if (readSuspended.compareAndSet(true, false)) {
if (eventLoop().inEventLoop()) { if (eventLoop().inEventLoop()) {
beginRead(); beginRead();
} else { } else {

View File

@ -31,9 +31,9 @@ abstract class AbstractNioByteChannel extends AbstractNioChannel {
} }
@Override @Override
protected abstract NioByteUnsafe newUnsafe(); protected abstract AbstractNioByteUnsafe newUnsafe();
protected abstract class NioByteUnsafe extends AbstractNioUnsafe { abstract class AbstractNioByteUnsafe extends AbstractNioUnsafe {
@Override @Override
public void read() { public void read() {
assert eventLoop().inEventLoop(); assert eventLoop().inEventLoop();

View File

@ -187,7 +187,6 @@ public abstract class AbstractNioChannel extends AbstractChannel {
connectFuture = null; connectFuture = null;
} }
} }
} }
@Override @Override

View File

@ -30,9 +30,9 @@ abstract class AbstractNioMessageChannel extends AbstractNioChannel {
} }
@Override @Override
protected abstract NioMessageUnsafe newUnsafe(); protected abstract AbstractNioMessageUnsafe newUnsafe();
abstract class NioMessageUnsafe extends AbstractNioUnsafe { abstract class AbstractNioMessageUnsafe extends AbstractNioUnsafe {
@Override @Override
public void read() { public void read() {
assert eventLoop().inEventLoop(); assert eventLoop().inEventLoop();

View File

@ -462,24 +462,20 @@ public final class NioDatagramChannel
} }
@Override @Override
protected NioMessageUnsafe newUnsafe() { protected AbstractNioMessageUnsafe newUnsafe() {
return new NioDatagramChannelUnsafe(); return new NioDatagramChannelUnsafe();
} }
private final class NioDatagramChannelUnsafe extends NioMessageUnsafe { private final class NioDatagramChannelUnsafe extends AbstractNioMessageUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {
if (!connected) { selectionKey().interestOps(selectionKey().interestOps() & ~ SelectionKey.OP_READ);
selectionKey().interestOps(selectionKey().interestOps() & ~ SelectionKey.OP_READ);
}
} }
@Override @Override
public void resumeRead() { public void resumeRead() {
if (!connected) { selectionKey().interestOps(selectionKey().interestOps() & ~ SelectionKey.OP_READ);
selectionKey().interestOps(selectionKey().interestOps() & ~ SelectionKey.OP_READ);
}
} }
} }
} }

View File

@ -130,11 +130,11 @@ public class NioServerSocketChannel extends AbstractNioMessageChannel
} }
@Override @Override
protected NioMessageUnsafe newUnsafe() { protected AbstractNioMessageUnsafe newUnsafe() {
return new NioServerSocketUnsafe(); return new NioServerSocketUnsafe();
} }
private final class NioServerSocketUnsafe extends NioMessageUnsafe { private final class NioServerSocketUnsafe extends AbstractNioMessageUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {
selectionKey().interestOps(selectionKey().interestOps() & ~ SelectionKey.OP_ACCEPT); selectionKey().interestOps(selectionKey().interestOps() & ~ SelectionKey.OP_ACCEPT);

View File

@ -193,11 +193,11 @@ public class NioSocketChannel extends AbstractNioByteChannel implements io.netty
} }
@Override @Override
protected NioByteUnsafe newUnsafe() { protected AbstractNioByteUnsafe newUnsafe() {
return new NioSocketChannelUnsafe(); return new NioSocketChannelUnsafe();
} }
private final class NioSocketChannelUnsafe extends NioByteUnsafe { private final class NioSocketChannelUnsafe extends AbstractNioByteUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {

View File

@ -28,9 +28,9 @@ abstract class AbstractOioByteChannel extends AbstractOioChannel {
} }
@Override @Override
protected abstract OioByteUnsafe newUnsafe(); protected abstract AbstractOioByteUnsafe newUnsafe();
abstract class OioByteUnsafe extends AbstractOioUnsafe { abstract class AbstractOioByteUnsafe extends AbstractOioUnsafe {
@Override @Override
public void read() { public void read() {
assert eventLoop().inEventLoop(); assert eventLoop().inEventLoop();

View File

@ -50,7 +50,7 @@ abstract class AbstractOioChannel extends AbstractChannel {
void read(); void read();
} }
protected abstract class AbstractOioUnsafe extends AbstractUnsafe implements OioUnsafe { abstract class AbstractOioUnsafe extends AbstractUnsafe implements OioUnsafe {
@Override @Override
public void connect( public void connect(

View File

@ -28,9 +28,9 @@ abstract class AbstractOioMessageChannel extends AbstractOioChannel {
} }
@Override @Override
protected abstract OioMessageUnsafe newUnsafe(); protected abstract AbstractOioMessageUnsafe newUnsafe();
abstract class OioMessageUnsafe extends AbstractOioUnsafe { abstract class AbstractOioMessageUnsafe extends AbstractOioUnsafe {
@Override @Override
public void read() { public void read() {
assert eventLoop().inEventLoop(); assert eventLoop().inEventLoop();

View File

@ -52,7 +52,7 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
private final DatagramChannelConfig config; private final DatagramChannelConfig config;
private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EMPTY_DATA, 0); private final java.net.DatagramPacket tmpPacket = new java.net.DatagramPacket(EMPTY_DATA, 0);
private volatile boolean readSuspend; private volatile boolean readSuspended;
private static MulticastSocket newSocket() { private static MulticastSocket newSocket() {
try { try {
@ -165,7 +165,7 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
@Override @Override
protected int doReadMessages(MessageBuf<Object> buf) throws Exception { protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
if (readSuspend) { if (readSuspended) {
try { try {
Thread.sleep(SO_TIMEOUT); Thread.sleep(SO_TIMEOUT);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -186,7 +186,7 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
buf.add(new DatagramPacket(Unpooled.wrappedBuffer( buf.add(new DatagramPacket(Unpooled.wrappedBuffer(
data, tmpPacket.getOffset(), tmpPacket.getLength()), remoteAddr)); data, tmpPacket.getOffset(), tmpPacket.getLength()), remoteAddr));
if (readSuspend) { if (readSuspended) {
return 0; return 0;
} else { } else {
return 1; return 1;
@ -354,20 +354,20 @@ public class OioDatagramChannel extends AbstractOioMessageChannel
} }
@Override @Override
protected OioMessageUnsafe newUnsafe() { protected AbstractOioMessageUnsafe newUnsafe() {
return new OioDatagramChannelUnsafe(); return new OioDatagramChannelUnsafe();
} }
private final class OioDatagramChannelUnsafe extends OioMessageUnsafe { private final class OioDatagramChannelUnsafe extends AbstractOioMessageUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {
readSuspend = true; readSuspended = true;
} }
@Override @Override
public void resumeRead() { public void resumeRead() {
readSuspend = false; readSuspended = false;
} }
} }
} }

View File

@ -54,7 +54,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
final Lock shutdownLock = new ReentrantLock(); final Lock shutdownLock = new ReentrantLock();
private final ServerSocketChannelConfig config; private final ServerSocketChannelConfig config;
private volatile boolean readSuspend; private volatile boolean readSuspended;
public OioServerSocketChannel() { public OioServerSocketChannel() {
this(newServerSocket()); this(newServerSocket());
@ -140,7 +140,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
return -1; return -1;
} }
if (readSuspend) { if (readSuspended) {
try { try {
Thread.sleep(SO_TIMEOUT); Thread.sleep(SO_TIMEOUT);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -154,7 +154,7 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
s = socket.accept(); s = socket.accept();
if (s != null) { if (s != null) {
buf.add(new OioSocketChannel(this, null, s)); buf.add(new OioSocketChannel(this, null, s));
if (readSuspend) { if (readSuspended) {
return 0; return 0;
} }
return 1; return 1;
@ -197,20 +197,20 @@ public class OioServerSocketChannel extends AbstractOioMessageChannel
} }
@Override @Override
protected OioMessageUnsafe newUnsafe() { protected AbstractOioMessageUnsafe newUnsafe() {
return new OioServerSocketUnsafe(); return new OioServerSocketUnsafe();
} }
private final class OioServerSocketUnsafe extends OioMessageUnsafe { private final class OioServerSocketUnsafe extends AbstractOioMessageUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {
readSuspend = true; readSuspended = true;
} }
@Override @Override
public void resumeRead() { public void resumeRead() {
readSuspend = false; readSuspended = false;
} }
} }
} }

View File

@ -46,7 +46,7 @@ public class OioSocketChannel extends AbstractOioByteChannel
private final SocketChannelConfig config; private final SocketChannelConfig config;
private InputStream is; private InputStream is;
private OutputStream os; private OutputStream os;
private volatile boolean suspendRead; private volatile boolean readSuspended;
public OioSocketChannel() { public OioSocketChannel() {
this(new Socket()); this(new Socket());
@ -162,7 +162,7 @@ public class OioSocketChannel extends AbstractOioByteChannel
return -1; return -1;
} }
if (suspendRead) { if (readSuspended) {
try { try {
Thread.sleep(SO_TIMEOUT); Thread.sleep(SO_TIMEOUT);
} catch (InterruptedException e) { } catch (InterruptedException e) {
@ -173,7 +173,7 @@ public class OioSocketChannel extends AbstractOioByteChannel
try { try {
int read = buf.writeBytes(is, buf.writableBytes()); int read = buf.writeBytes(is, buf.writableBytes());
if (read > 0 && !suspendRead) { if (read > 0 && !readSuspended) {
return read; return read;
} else { } else {
// so the read bytes were 0 or the read was suspend // so the read bytes were 0 or the read was suspend
@ -195,20 +195,20 @@ public class OioSocketChannel extends AbstractOioByteChannel
@Override @Override
protected OioByteUnsafe newUnsafe() { protected AbstractOioByteUnsafe newUnsafe() {
return new OioSocketChannelUnsafe(); return new OioSocketChannelUnsafe();
} }
private final class OioSocketChannelUnsafe extends OioByteUnsafe { private final class OioSocketChannelUnsafe extends AbstractOioByteUnsafe {
@Override @Override
public void suspendRead() { public void suspendRead() {
suspendRead = true; readSuspended = true;
} }
@Override @Override
public void resumeRead() { public void resumeRead() {
suspendRead = false; readSuspended = false;
} }
} }
} }