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

@ -27,15 +27,11 @@ package sun.nio.ch;
import java.io.IOException;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.spi.SelectorProvider;
import java.util.ArrayDeque;
import java.util.BitSet;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@ -66,15 +62,11 @@ class KQueueSelectorImpl extends SelectorImpl {
// maps file descriptor to selection key, synchronize on selector
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
// file descriptors registered with kqueue, synchronize on selector
private final BitSet registeredReadFilter = new BitSet();
private final BitSet registeredWriteFilter = new BitSet();
// pending new registrations/updates, queued by implRegister and putEventOps
private final Object updateLock = new Object();
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
private final Deque<Integer> updateOps = new ArrayDeque<>();
private final Deque<Integer> updateEvents = new ArrayDeque<>();
// interrupt triggering and clearing
private final Object interruptLock = new Object();
@ -113,14 +105,16 @@ class KQueueSelectorImpl extends SelectorImpl {
protected int doSelect(long timeout) throws IOException {
assert Thread.holdsLock(this);
long to = Math.min(timeout, Integer.MAX_VALUE); // max kqueue timeout
boolean blocking = (to != 0);
boolean timedPoll = (to > 0);
int numEntries;
processUpdateQueue();
processDeregisterQueue();
try {
begin();
begin(blocking);
long to = Math.min(timeout, Integer.MAX_VALUE); // max kqueue timeout
boolean timedPoll = (to > 0);
do {
long startTime = timedPoll ? System.nanoTime() : 0;
numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, to);
@ -137,7 +131,7 @@ class KQueueSelectorImpl extends SelectorImpl {
assert IOStatus.check(numEntries);
} finally {
end();
end(blocking);
}
processDeregisterQueue();
return updateSelectedKeys(numEntries);
@ -155,41 +149,41 @@ class KQueueSelectorImpl extends SelectorImpl {
// new registrations
while ((ski = newKeys.pollFirst()) != null) {
if (ski.isValid()) {
SelChImpl ch = ski.channel;
int fd = ch.getFDVal();
int fd = ski.channel.getFDVal();
SelectionKeyImpl previous = fdToKey.put(fd, ski);
assert previous == null;
assert registeredReadFilter.get(fd) == false;
assert registeredWriteFilter.get(fd) == false;
assert ski.registeredEvents() == 0;
}
}
// changes to interest ops
assert updateKeys.size() == updateOps.size();
assert updateKeys.size() == updateKeys.size();
while ((ski = updateKeys.pollFirst()) != null) {
int ops = updateOps.pollFirst();
int newEvents = updateEvents.pollFirst();
int fd = ski.channel.getFDVal();
if (ski.isValid() && fdToKey.containsKey(fd)) {
// add or delete interest in read events
if (registeredReadFilter.get(fd)) {
if ((ops & Net.POLLIN) == 0) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
registeredReadFilter.clear(fd);
}
} else if ((ops & Net.POLLIN) != 0) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_ADD);
registeredReadFilter.set(fd);
}
int registeredEvents = ski.registeredEvents();
if (newEvents != registeredEvents) {
// add or delete interest in write events
if (registeredWriteFilter.get(fd)) {
if ((ops & Net.POLLOUT) == 0) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
registeredWriteFilter.clear(fd);
// add or delete interest in read events
if ((registeredEvents & Net.POLLIN) != 0) {
if ((newEvents & Net.POLLIN) == 0) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
}
} else if ((newEvents & Net.POLLIN) != 0) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_ADD);
}
} else if ((ops & Net.POLLOUT) != 0) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_ADD);
registeredWriteFilter.set(fd);
// add or delete interest in write events
if ((registeredEvents & Net.POLLOUT) != 0) {
if ((newEvents & Net.POLLOUT) == 0) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
}
} else if ((newEvents & Net.POLLOUT) != 0) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_ADD);
}
ski.registeredEvents(newEvents);
}
}
}
@ -197,8 +191,8 @@ class KQueueSelectorImpl extends SelectorImpl {
}
/**
* Update the keys whose fd's have been selected by kqueue.
* Add the ready keys to the selected key set.
* Update the keys of file descriptors that were polled and add them to
* the selected-key set.
* If the interrupt fd has been selected, drain it and clear the interrupt.
*/
private int updateSelectedKeys(int numEntries) throws IOException {
@ -265,7 +259,6 @@ class KQueueSelectorImpl extends SelectorImpl {
protected void implClose() throws IOException {
assert !isOpen();
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioKeys());
// prevent further wakeup
synchronized (interruptLock) {
@ -277,63 +270,41 @@ class KQueueSelectorImpl extends SelectorImpl {
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
// 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();
i.remove();
}
}
@Override
protected void implRegister(SelectionKeyImpl ski) {
assert Thread.holdsLock(nioKeys());
ensureOpen();
synchronized (updateLock) {
newKeys.addLast(ski);
}
keys.add(ski);
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
assert !ski.isValid();
assert Thread.holdsLock(this);
assert Thread.holdsLock(nioKeys());
assert Thread.holdsLock(nioSelectedKeys());
int fd = ski.channel.getFDVal();
fdToKey.remove(fd);
if (registeredReadFilter.get(fd)) {
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
registeredReadFilter.clear(fd);
int registeredEvents = ski.registeredEvents();
if (fdToKey.remove(fd) != null) {
if (registeredEvents != 0) {
if ((registeredEvents & Net.POLLIN) != 0)
KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
if ((registeredEvents & Net.POLLOUT) != 0)
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
ski.registeredEvents(0);
}
} else {
assert registeredEvents == 0;
}
if (registeredWriteFilter.get(fd)) {
KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
registeredWriteFilter.clear(fd);
}
selectedKeys.remove(ski);
keys.remove(ski);
// remove from channel's key set
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl) selch).kill();
}
@Override
public void putEventOps(SelectionKeyImpl ski, int ops) {
public void putEventOps(SelectionKeyImpl ski, int events) {
ensureOpen();
synchronized (updateLock) {
updateOps.addLast(ops); // ops first in case adding the key fails
updateEvents.addLast(events); // events first in case adding key fails
updateKeys.addLast(ski);
}
}