NIO autoReadClear should also clear the SelectionKey

Motivation:
Prior to 5b48fc284e setting readPending to false when autoReadClear was called was enough because when/if the EventLoop woke up with a read event we would first check if readPending was true and if it is not, we would return early. Now that readPending will only be set in the EventLoop it is not necessary to check readPending at the start of the read methods, and we should instead remove the OP_READ from the SelectionKey when we also set readPending to false.

Modifications:
- autoReadCleared should call AbstractNioUnsafe.removeReadOp

Result:
NIO is now consistent with EPOLL and removes the READ operation on the selector when autoRead is cleared.
This commit is contained in:
Scott Mitchell 2016-04-07 19:49:02 -07:00
parent 562d8d2200
commit 0bc93dda08

View File

@ -65,7 +65,7 @@ public abstract class AbstractNioChannel extends AbstractChannel {
private final Runnable clearReadPendingRunnable = new Runnable() { private final Runnable clearReadPendingRunnable = new Runnable() {
@Override @Override
public void run() { public void run() {
readPending = false; clearReadPending0();
} }
}; };
@ -149,17 +149,17 @@ public abstract class AbstractNioChannel extends AbstractChannel {
if (isRegistered()) { if (isRegistered()) {
EventLoop eventLoop = eventLoop(); EventLoop eventLoop = eventLoop();
if (eventLoop.inEventLoop()) { if (eventLoop.inEventLoop()) {
this.readPending = readPending; setReadPending0(readPending);
} else { } else {
eventLoop.execute(new OneTimeTask() { eventLoop.execute(new OneTimeTask() {
@Override @Override
public void run() { public void run() {
AbstractNioChannel.this.readPending = readPending; setReadPending0(readPending);
} }
}); });
} }
} else { } else {
this.readPending = readPending; setReadPending0(readPending);
} }
} }
@ -170,16 +170,28 @@ public abstract class AbstractNioChannel extends AbstractChannel {
if (isRegistered()) { if (isRegistered()) {
EventLoop eventLoop = eventLoop(); EventLoop eventLoop = eventLoop();
if (eventLoop.inEventLoop()) { if (eventLoop.inEventLoop()) {
readPending = false; clearReadPending0();
} else { } else {
eventLoop.execute(clearReadPendingRunnable); eventLoop.execute(clearReadPendingRunnable);
} }
} else { } else {
// Best effort if we are not registered yet clear readPending. This happens during channel initialization. // Best effort if we are not registered yet clear readPending. This happens during channel initialization.
readPending = false; clearReadPending0();
} }
} }
private void setReadPending0(boolean readPending) {
this.readPending = readPending;
if (!readPending) {
((AbstractNioUnsafe) unsafe()).removeReadOp();
}
}
private void clearReadPending0() {
readPending = false;
((AbstractNioUnsafe) unsafe()).removeReadOp();
}
/** /**
* Return {@code true} if the input of this {@link Channel} is shutdown * Return {@code true} if the input of this {@link Channel} is shutdown
*/ */