8200257: (se) More Selector cleanup

Reviewed-by: bpb
This commit is contained in:
Alan Bateman 2018-03-30 08:28:09 +01:00
parent 8a1bee438c
commit 34c94079ed
20 changed files with 457 additions and 548 deletions

View file

@ -1229,10 +1229,9 @@ class DatagramChannelImpl
/**
* Translates native poll revent set into a ready operation set
*/
public boolean translateReadyOps(int ops, int initialOps,
SelectionKeyImpl sk) {
int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
int oldOps = sk.nioReadyOps();
public boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl ski) {
int intOps = ski.nioInterestOps();
int oldOps = ski.nioReadyOps();
int newOps = initialOps;
if ((ops & Net.POLLNVAL) != 0) {
@ -1244,7 +1243,7 @@ class DatagramChannelImpl
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
newOps = intOps;
sk.nioReadyOps(newOps);
ski.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
@ -1256,16 +1255,16 @@ class DatagramChannelImpl
((intOps & SelectionKey.OP_WRITE) != 0))
newOps |= SelectionKey.OP_WRITE;
sk.nioReadyOps(newOps);
ski.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
return translateReadyOps(ops, sk.nioReadyOps(), sk);
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
return translateReadyOps(ops, ski.nioReadyOps(), ski);
}
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
return translateReadyOps(ops, 0, sk);
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
return translateReadyOps(ops, 0, ski);
}
/**
@ -1295,16 +1294,15 @@ class DatagramChannelImpl
/**
* Translates an interest operation set into a native poll event set
*/
public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
public int translateInterestOps(int ops) {
int newOps = 0;
if ((ops & SelectionKey.OP_READ) != 0)
newOps |= Net.POLLIN;
if ((ops & SelectionKey.OP_WRITE) != 0)
newOps |= Net.POLLOUT;
if ((ops & SelectionKey.OP_CONNECT) != 0)
newOps |= Net.POLLIN;
sk.selector.putEventOps(sk, newOps);
return newOps;
}
public FileDescriptor getFD() {

View file

@ -61,7 +61,10 @@ public interface SelChImpl extends Channel {
*/
boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk);
void translateAndSetInterestOps(int ops, SelectionKeyImpl sk);
/**
* Translates an interest operation set into a native event set
*/
int translateInterestOps(int ops);
void kill() throws IOException;

View file

@ -39,21 +39,28 @@ import java.nio.channels.spi.AbstractSelectionKey;
public final class SelectionKeyImpl
extends AbstractSelectionKey
{
final SelChImpl channel; // package-private
public final SelectorImpl selector;
// Index for a pollfd array in Selector that this key is registered with
private int index;
private final SelectorImpl selector;
private volatile int interestOps;
private volatile int readyOps;
// registered events in kernel, used by some Selector implementations
private int registeredEvents;
// index of key in pollfd array, used by some Selector implementations
private int index;
SelectionKeyImpl(SelChImpl ch, SelectorImpl sel) {
channel = ch;
selector = sel;
}
private void ensureValid() {
if (!isValid())
throw new CancelledKeyException();
}
@Override
public SelectableChannel channel() {
return (SelectableChannel)channel;
@ -61,20 +68,7 @@ public final class SelectionKeyImpl
@Override
public Selector selector() {
return (Selector)selector;
}
int getIndex() { // package-private
return index;
}
void setIndex(int i) { // package-private
index = i;
}
private void ensureValid() {
if (!isValid())
throw new CancelledKeyException();
return selector;
}
@Override
@ -109,7 +103,7 @@ public final class SelectionKeyImpl
public SelectionKey nioInterestOps(int ops) {
if ((ops & ~channel().validOps()) != 0)
throw new IllegalArgumentException();
channel.translateAndSetInterestOps(ops, this);
selector.putEventOps(this, channel.translateInterestOps(ops));
interestOps = ops;
return this;
}
@ -118,6 +112,24 @@ public final class SelectionKeyImpl
return interestOps;
}
void registeredEvents(int events) {
// assert Thread.holdsLock(selector);
this.registeredEvents = events;
}
int registeredEvents() {
// assert Thread.holdsLock(selector);
return registeredEvents;
}
int getIndex() {
return index;
}
void setIndex(int i) {
index = i;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();

View file

@ -26,9 +26,9 @@
package sun.nio.ch;
import java.io.IOException;
import java.net.SocketException;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.IllegalSelectorException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.AbstractSelector;
@ -47,7 +47,7 @@ public abstract class SelectorImpl
extends AbstractSelector
{
// The set of keys registered with this Selector
protected final HashSet<SelectionKey> keys;
protected final Set<SelectionKey> keys;
// The set of keys with data ready for an operation
protected final Set<SelectionKey> selectedKeys;
@ -88,6 +88,26 @@ public abstract class SelectorImpl
return publicSelectedKeys;
}
/**
* Marks the beginning of a select operation that might block
*/
protected final void begin(boolean blocking) {
if (blocking) begin();
}
/**
* Marks the end of a select operation that may have blocked
*/
protected final void end(boolean blocking) {
if (blocking) end();
}
/**
* Selects the keys for channels that are ready for I/O operations.
*
* @param timeout timeout in milliseconds to wait, 0 to not wait, -1 to
* wait indefinitely
*/
protected abstract int doSelect(long timeout) throws IOException;
private int lockAndDoSelect(long timeout) throws IOException {
@ -125,9 +145,21 @@ public abstract class SelectorImpl
public final void implCloseSelector() throws IOException {
wakeup();
synchronized (this) {
implClose();
synchronized (publicKeys) {
synchronized (publicSelectedKeys) {
implClose();
// Deregister channels
Iterator<SelectionKey> i = keys.iterator();
while (i.hasNext()) {
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
selectedKeys.remove(ski);
i.remove();
}
assert selectedKeys.isEmpty() && keys.isEmpty();
}
}
}
@ -144,8 +176,10 @@ public abstract class SelectorImpl
throw new IllegalSelectorException();
SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
k.attach(attachment);
// register before adding to key set
implRegister(k);
synchronized (publicKeys) {
implRegister(k);
keys.add(k);
}
k.interestOps(ops);
return k;
@ -156,27 +190,37 @@ public abstract class SelectorImpl
protected abstract void implDereg(SelectionKeyImpl ski) throws IOException;
protected final void processDeregisterQueue() throws IOException {
// Precondition: Synchronized on this, keys, and selectedKeys
assert Thread.holdsLock(this);
assert Thread.holdsLock(publicKeys);
assert Thread.holdsLock(publicSelectedKeys);
Set<SelectionKey> cks = cancelledKeys();
synchronized (cks) {
if (!cks.isEmpty()) {
Iterator<SelectionKey> i = cks.iterator();
while (i.hasNext()) {
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
try {
implDereg(ski);
} catch (SocketException se) {
throw new IOException("Error deregistering key", se);
} finally {
i.remove();
}
i.remove();
// remove the key from the selector
implDereg(ski);
selectedKeys.remove(ski);
keys.remove(ski);
// remove from channel's key set
deregister(ski);
SelectableChannel ch = ski.channel();
if (!ch.isOpen() && !ch.isRegistered())
((SelChImpl)ch).kill();
}
}
}
}
/**
* Invoked to change the key's interest set
* Change the event set in the selector
*/
public abstract void putEventOps(SelectionKeyImpl ski, int ops);
protected abstract void putEventOps(SelectionKeyImpl ski, int events);
}

View file

@ -445,10 +445,9 @@ class ServerSocketChannelImpl
/**
* Translates native poll revent set into a ready operation set
*/
public boolean translateReadyOps(int ops, int initialOps,
SelectionKeyImpl sk) {
int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
int oldOps = sk.nioReadyOps();
public boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl ski) {
int intOps = ski.nioInterestOps();
int oldOps = ski.nioReadyOps();
int newOps = initialOps;
if ((ops & Net.POLLNVAL) != 0) {
@ -460,7 +459,7 @@ class ServerSocketChannelImpl
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
newOps = intOps;
sk.nioReadyOps(newOps);
ski.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
@ -468,29 +467,26 @@ class ServerSocketChannelImpl
((intOps & SelectionKey.OP_ACCEPT) != 0))
newOps |= SelectionKey.OP_ACCEPT;
sk.nioReadyOps(newOps);
ski.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
return translateReadyOps(ops, sk.nioReadyOps(), sk);
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
return translateReadyOps(ops, ski.nioReadyOps(), ski);
}
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
return translateReadyOps(ops, 0, sk);
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
return translateReadyOps(ops, 0, ski);
}
/**
* Translates an interest operation set into a native poll event set
*/
public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
public int translateInterestOps(int ops) {
int newOps = 0;
// Translate ops
if ((ops & SelectionKey.OP_ACCEPT) != 0)
newOps |= Net.POLLIN;
// Place ops into pollfd array
sk.selector.putEventOps(sk, newOps);
return newOps;
}
public FileDescriptor getFD() {

View file

@ -994,10 +994,9 @@ class SocketChannelImpl
/**
* Translates native poll revent ops into a ready operation ops
*/
public boolean translateReadyOps(int ops, int initialOps,
SelectionKeyImpl sk) {
int intOps = sk.nioInterestOps(); // Do this just once, it synchronizes
int oldOps = sk.nioReadyOps();
public boolean translateReadyOps(int ops, int initialOps, SelectionKeyImpl ski) {
int intOps = ski.nioInterestOps();
int oldOps = ski.nioReadyOps();
int newOps = initialOps;
if ((ops & Net.POLLNVAL) != 0) {
@ -1009,7 +1008,7 @@ class SocketChannelImpl
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
newOps = intOps;
sk.nioReadyOps(newOps);
ski.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
@ -1026,22 +1025,22 @@ class SocketChannelImpl
((intOps & SelectionKey.OP_WRITE) != 0) && connected)
newOps |= SelectionKey.OP_WRITE;
sk.nioReadyOps(newOps);
ski.nioReadyOps(newOps);
return (newOps & ~oldOps) != 0;
}
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk) {
return translateReadyOps(ops, sk.nioReadyOps(), sk);
public boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski) {
return translateReadyOps(ops, ski.nioReadyOps(), ski);
}
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk) {
return translateReadyOps(ops, 0, sk);
public boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski) {
return translateReadyOps(ops, 0, ski);
}
/**
* Translates an interest operation set into a native poll event set
*/
public void translateAndSetInterestOps(int ops, SelectionKeyImpl sk) {
public int translateInterestOps(int ops) {
int newOps = 0;
if ((ops & SelectionKey.OP_READ) != 0)
newOps |= Net.POLLIN;
@ -1049,7 +1048,7 @@ class SocketChannelImpl
newOps |= Net.POLLOUT;
if ((ops & SelectionKey.OP_CONNECT) != 0)
newOps |= Net.POLLCONN;
sk.selector.putEventOps(sk, newOps);
return newOps;
}
public FileDescriptor getFD() {