8200583: (se) Selector clean-up, part 4
Reviewed-by: bpb, chegar
This commit is contained in:
parent
9968548d57
commit
d185d65b69
src/java.base
linux/classes/sun/nio/ch
macosx/classes/sun/nio/ch
share/classes/sun/nio/ch
solaris
classes/sun/nio/ch
native/libnio/ch
unix/classes/sun/nio/ch
windows/classes/sun/nio/ch
@ -63,20 +63,14 @@ class EPollSelectorImpl extends SelectorImpl {
|
||||
// maps file descriptor to selection key, synchronize on selector
|
||||
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
|
||||
|
||||
// pending new registrations/updates, queued by implRegister and putEventOpos
|
||||
// pending new registrations/updates, queued by setEventOps
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
private final Deque<Integer> updateEvents = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
private boolean interruptTriggered;
|
||||
|
||||
/**
|
||||
* Package private constructor called by factory method in
|
||||
* the abstract superclass Selector.
|
||||
*/
|
||||
EPollSelectorImpl(SelectorProvider sp) throws IOException {
|
||||
super(sp);
|
||||
|
||||
@ -140,30 +134,21 @@ class EPollSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process new registrations and changes to the interest ops.
|
||||
* Process changes to the interest ops.
|
||||
*/
|
||||
private void processUpdateQueue() {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
synchronized (updateLock) {
|
||||
SelectionKeyImpl ski;
|
||||
|
||||
// new registrations
|
||||
while ((ski = newKeys.pollFirst()) != null) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.channel.getFDVal();
|
||||
SelectionKeyImpl previous = fdToKey.put(fd, ski);
|
||||
assert previous == null;
|
||||
assert ski.registeredEvents() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// changes to interest ops
|
||||
assert updateKeys.size() == updateEvents.size();
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
int newEvents = updateEvents.pollFirst();
|
||||
int fd = ski.channel.getFDVal();
|
||||
if (ski.isValid() && fdToKey.containsKey(fd)) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.getFDVal();
|
||||
// add to fdToKey if needed
|
||||
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
|
||||
assert (previous == null) || (previous == ski);
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
int registeredEvents = ski.registeredEvents();
|
||||
if (newEvents != registeredEvents) {
|
||||
if (newEvents == 0) {
|
||||
@ -206,11 +191,11 @@ class EPollSelectorImpl extends SelectorImpl {
|
||||
if (ski != null) {
|
||||
int rOps = EPoll.getEvents(event);
|
||||
if (selectedKeys.contains(ski)) {
|
||||
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
|
||||
if (ski.translateAndSetReadyOps(rOps)) {
|
||||
numKeysUpdated++;
|
||||
}
|
||||
} else {
|
||||
ski.channel.translateAndSetReadyOps(rOps, ski);
|
||||
ski.translateAndSetReadyOps(rOps);
|
||||
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(ski);
|
||||
numKeysUpdated++;
|
||||
@ -243,20 +228,12 @@ class EPollSelectorImpl extends SelectorImpl {
|
||||
FileDispatcherImpl.closeIntFD(fd1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implRegister(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
newKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
assert !ski.isValid();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int fd = ski.channel.getFDVal();
|
||||
int fd = ski.getFDVal();
|
||||
if (fdToKey.remove(fd) != null) {
|
||||
if (ski.registeredEvents() != 0) {
|
||||
EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
|
||||
@ -268,10 +245,9 @@ class EPollSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putEventOps(SelectionKeyImpl ski, int events) {
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateEvents.addLast(events); // events first in case adding key fails
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
@ -62,11 +62,9 @@ class KQueueSelectorImpl extends SelectorImpl {
|
||||
// maps file descriptor to selection key, synchronize on selector
|
||||
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
|
||||
|
||||
// pending new registrations/updates, queued by implRegister and putEventOps
|
||||
// pending new registrations/updates, queued by setEventOps
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
private final Deque<Integer> updateEvents = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
@ -138,30 +136,21 @@ class KQueueSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Process new registrations and changes to the interest ops.
|
||||
* Process changes to the interest ops.
|
||||
*/
|
||||
private void processUpdateQueue() {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
synchronized (updateLock) {
|
||||
SelectionKeyImpl ski;
|
||||
|
||||
// new registrations
|
||||
while ((ski = newKeys.pollFirst()) != null) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.channel.getFDVal();
|
||||
SelectionKeyImpl previous = fdToKey.put(fd, ski);
|
||||
assert previous == null;
|
||||
assert ski.registeredEvents() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// changes to interest ops
|
||||
assert updateKeys.size() == updateKeys.size();
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
int newEvents = updateEvents.pollFirst();
|
||||
int fd = ski.channel.getFDVal();
|
||||
if (ski.isValid() && fdToKey.containsKey(fd)) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.getFDVal();
|
||||
// add to fdToKey if needed
|
||||
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
|
||||
assert (previous == null) || (previous == ski);
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
int registeredEvents = ski.registeredEvents();
|
||||
if (newEvents != registeredEvents) {
|
||||
|
||||
@ -229,16 +218,16 @@ class KQueueSelectorImpl extends SelectorImpl {
|
||||
if (selectedKeys.contains(ski)) {
|
||||
// file descriptor may be polled more than once per poll
|
||||
if (ski.lastPolled != pollCount) {
|
||||
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
|
||||
if (ski.translateAndSetReadyOps(rOps)) {
|
||||
numKeysUpdated++;
|
||||
ski.lastPolled = pollCount;
|
||||
}
|
||||
} else {
|
||||
// ready ops have already been set on this update
|
||||
ski.channel.translateAndUpdateReadyOps(rOps, ski);
|
||||
ski.translateAndUpdateReadyOps(rOps);
|
||||
}
|
||||
} else {
|
||||
ski.channel.translateAndSetReadyOps(rOps, ski);
|
||||
ski.translateAndSetReadyOps(rOps);
|
||||
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(ski);
|
||||
numKeysUpdated++;
|
||||
@ -272,20 +261,12 @@ class KQueueSelectorImpl extends SelectorImpl {
|
||||
FileDispatcherImpl.closeIntFD(fd1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implRegister(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
newKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
assert !ski.isValid();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int fd = ski.channel.getFDVal();
|
||||
int fd = ski.getFDVal();
|
||||
int registeredEvents = ski.registeredEvents();
|
||||
if (fdToKey.remove(fd) != null) {
|
||||
if (registeredEvents != 0) {
|
||||
@ -301,10 +282,9 @@ class KQueueSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putEventOps(SelectionKeyImpl ski, int events) {
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateEvents.addLast(events); // events first in case adding key fails
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public interface SelChImpl extends Channel {
|
||||
* contains at least one bit that the previous value did not
|
||||
* contain
|
||||
*/
|
||||
boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl sk);
|
||||
boolean translateAndUpdateReadyOps(int ops, SelectionKeyImpl ski);
|
||||
|
||||
/**
|
||||
* Sets the specified ops if present in interestOps. The specified
|
||||
@ -59,7 +59,7 @@ public interface SelChImpl extends Channel {
|
||||
* contains at least one bit that the previous value did not
|
||||
* contain
|
||||
*/
|
||||
boolean translateAndSetReadyOps(int ops, SelectionKeyImpl sk);
|
||||
boolean translateAndSetReadyOps(int ops, SelectionKeyImpl ski);
|
||||
|
||||
/**
|
||||
* Translates an interest operation set into a native event set
|
||||
|
@ -39,7 +39,7 @@ import java.nio.channels.spi.AbstractSelectionKey;
|
||||
public final class SelectionKeyImpl
|
||||
extends AbstractSelectionKey
|
||||
{
|
||||
final SelChImpl channel; // package-private
|
||||
private final SelChImpl channel;
|
||||
private final SelectorImpl selector;
|
||||
|
||||
private volatile int interestOps;
|
||||
@ -61,6 +61,10 @@ public final class SelectionKeyImpl
|
||||
throw new CancelledKeyException();
|
||||
}
|
||||
|
||||
int getFDVal() {
|
||||
return channel.getFDVal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectableChannel channel() {
|
||||
return (SelectableChannel)channel;
|
||||
@ -103,8 +107,8 @@ public final class SelectionKeyImpl
|
||||
public SelectionKey nioInterestOps(int ops) {
|
||||
if ((ops & ~channel().validOps()) != 0)
|
||||
throw new IllegalArgumentException();
|
||||
selector.putEventOps(this, channel.translateInterestOps(ops));
|
||||
interestOps = ops;
|
||||
selector.setEventOps(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -112,6 +116,18 @@ public final class SelectionKeyImpl
|
||||
return interestOps;
|
||||
}
|
||||
|
||||
int translateInterestOps() {
|
||||
return channel.translateInterestOps(interestOps);
|
||||
}
|
||||
|
||||
boolean translateAndSetReadyOps(int ops) {
|
||||
return channel.translateAndSetReadyOps(ops, this);
|
||||
}
|
||||
|
||||
boolean translateAndUpdateReadyOps(int ops) {
|
||||
return channel.translateAndUpdateReadyOps(ops, this);
|
||||
}
|
||||
|
||||
void registeredEvents(int events) {
|
||||
// assert Thread.holdsLock(selector);
|
||||
this.registeredEvents = events;
|
||||
|
@ -64,17 +64,20 @@ public abstract class SelectorImpl
|
||||
publicSelectedKeys = Util.ungrowableSet(selectedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<SelectionKey> keys() {
|
||||
private void ensureOpen() {
|
||||
if (!isOpen())
|
||||
throw new ClosedSelectorException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<SelectionKey> keys() {
|
||||
ensureOpen();
|
||||
return publicKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Set<SelectionKey> selectedKeys() {
|
||||
if (!isOpen())
|
||||
throw new ClosedSelectorException();
|
||||
ensureOpen();
|
||||
return publicSelectedKeys;
|
||||
}
|
||||
|
||||
@ -112,8 +115,7 @@ public abstract class SelectorImpl
|
||||
|
||||
private int lockAndDoSelect(long timeout) throws IOException {
|
||||
synchronized (this) {
|
||||
if (!isOpen())
|
||||
throw new ClosedSelectorException();
|
||||
ensureOpen();
|
||||
synchronized (publicKeys) {
|
||||
synchronized (publicSelectedKeys) {
|
||||
return doSelect(timeout);
|
||||
@ -176,7 +178,8 @@ public abstract class SelectorImpl
|
||||
throw new IllegalSelectorException();
|
||||
SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
|
||||
k.attach(attachment);
|
||||
// register before adding to key set
|
||||
|
||||
// register with selector (if needed) before adding to key set
|
||||
implRegister(k);
|
||||
synchronized (publicKeys) {
|
||||
keys.add(k);
|
||||
@ -185,7 +188,15 @@ public abstract class SelectorImpl
|
||||
return k;
|
||||
}
|
||||
|
||||
protected abstract void implRegister(SelectionKeyImpl ski);
|
||||
/**
|
||||
* Register the key in the selector.
|
||||
*
|
||||
* The default implementation checks if the selector is open. It should
|
||||
* be overridden by selector implementations as needed.
|
||||
*/
|
||||
protected void implRegister(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
}
|
||||
|
||||
protected abstract void implDereg(SelectionKeyImpl ski) throws IOException;
|
||||
|
||||
@ -222,5 +233,5 @@ public abstract class SelectorImpl
|
||||
/**
|
||||
* Change the event set in the selector
|
||||
*/
|
||||
protected abstract void putEventOps(SelectionKeyImpl ski, int events);
|
||||
protected abstract void setEventOps(SelectionKeyImpl ski);
|
||||
}
|
||||
|
@ -55,17 +55,14 @@ class DevPollSelectorImpl
|
||||
// maps file descriptor to selection key, synchronize on selector
|
||||
private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
|
||||
|
||||
// pending new registrations/updates, queued by implRegister and putEventOps
|
||||
// pending new registrations/updates, queued by setEventOps
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
private final Deque<Integer> updateEvents = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
private boolean interruptTriggered;
|
||||
|
||||
|
||||
DevPollSelectorImpl(SelectorProvider sp) throws IOException {
|
||||
super(sp);
|
||||
this.pollWrapper = new DevPollArrayWrapper();
|
||||
@ -88,18 +85,34 @@ class DevPollSelectorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doSelect(long timeout)
|
||||
throws IOException
|
||||
{
|
||||
protected int doSelect(long timeout) throws IOException {
|
||||
assert Thread.holdsLock(this);
|
||||
boolean blocking = (timeout != 0);
|
||||
|
||||
long to = timeout;
|
||||
boolean blocking = (to != 0);
|
||||
boolean timedPoll = (to > 0);
|
||||
|
||||
int numEntries;
|
||||
processUpdateQueue();
|
||||
processDeregisterQueue();
|
||||
try {
|
||||
begin(blocking);
|
||||
numEntries = pollWrapper.poll(timeout);
|
||||
|
||||
do {
|
||||
long startTime = timedPoll ? System.nanoTime() : 0;
|
||||
numEntries = pollWrapper.poll(to);
|
||||
if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
|
||||
// timed poll interrupted so need to adjust timeout
|
||||
long adjust = System.nanoTime() - startTime;
|
||||
to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
|
||||
if (to <= 0) {
|
||||
// timeout expired so no retry
|
||||
numEntries = 0;
|
||||
}
|
||||
}
|
||||
} while (numEntries == IOStatus.INTERRUPTED);
|
||||
assert IOStatus.check(numEntries);
|
||||
|
||||
} finally {
|
||||
end(blocking);
|
||||
}
|
||||
@ -108,7 +121,7 @@ class DevPollSelectorImpl
|
||||
}
|
||||
|
||||
/**
|
||||
* Process new registrations and changes to the interest ops.
|
||||
* Process changes to the interest ops.
|
||||
*/
|
||||
private void processUpdateQueue() throws IOException {
|
||||
assert Thread.holdsLock(this);
|
||||
@ -116,25 +129,18 @@ class DevPollSelectorImpl
|
||||
synchronized (updateLock) {
|
||||
SelectionKeyImpl ski;
|
||||
|
||||
// new registrations
|
||||
while ((ski = newKeys.pollFirst()) != null) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.channel.getFDVal();
|
||||
SelectionKeyImpl previous = fdToKey.put(fd, ski);
|
||||
assert previous == null;
|
||||
assert ski.registeredEvents() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Translate the queued updates to changes to the set of monitored
|
||||
// file descriptors. The changes are written to the /dev/poll driver
|
||||
// in bulk.
|
||||
assert updateKeys.size() == updateEvents.size();
|
||||
int index = 0;
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
int newEvents = updateEvents.pollFirst();
|
||||
int fd = ski.channel.getFDVal();
|
||||
if (ski.isValid() && fdToKey.containsKey(fd)) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.getFDVal();
|
||||
// add to fdToKey if needed
|
||||
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
|
||||
assert (previous == null) || (previous == ski);
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
int registeredEvents = ski.registeredEvents();
|
||||
if (newEvents != registeredEvents) {
|
||||
if (registeredEvents != 0)
|
||||
@ -178,11 +184,11 @@ class DevPollSelectorImpl
|
||||
if (ski != null) {
|
||||
int rOps = pollWrapper.getReventOps(i);
|
||||
if (selectedKeys.contains(ski)) {
|
||||
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
|
||||
if (ski.translateAndSetReadyOps(rOps)) {
|
||||
numKeysUpdated++;
|
||||
}
|
||||
} else {
|
||||
ski.channel.translateAndSetReadyOps(rOps, ski);
|
||||
ski.translateAndSetReadyOps(rOps);
|
||||
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(ski);
|
||||
numKeysUpdated++;
|
||||
@ -214,20 +220,13 @@ class DevPollSelectorImpl
|
||||
FileDispatcherImpl.closeIntFD(fd1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implRegister(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
newKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
assert !ski.isValid();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int fd = ski.channel.getFDVal();
|
||||
int fd = ski.getFDVal();
|
||||
if (fdToKey.remove(fd) != null) {
|
||||
if (ski.registeredEvents() != 0) {
|
||||
pollWrapper.register(fd, POLLREMOVE);
|
||||
@ -239,10 +238,9 @@ class DevPollSelectorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putEventOps(SelectionKeyImpl ski, int events) {
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateEvents.addLast(events); // events first in case adding key fails
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
@ -72,12 +72,10 @@ class EventPortSelectorImpl
|
||||
// the last update operation, incremented by processUpdateQueue
|
||||
private int lastUpdate;
|
||||
|
||||
// pending new registrations/updates, queued by implRegister, putEventOps,
|
||||
// and updateSelectedKeys
|
||||
// pending new registrations/updates, queued by setEventOps and
|
||||
// updateSelectedKeys
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
private final Deque<Integer> updateEvents = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
@ -146,23 +144,14 @@ class EventPortSelectorImpl
|
||||
|
||||
synchronized (updateLock) {
|
||||
SelectionKeyImpl ski;
|
||||
|
||||
// new registrations
|
||||
while ((ski = newKeys.pollFirst()) != null) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.channel.getFDVal();
|
||||
SelectionKeyImpl previous = fdToKey.put(fd, ski);
|
||||
assert previous == null;
|
||||
assert ski.registeredEvents() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
// changes to interest ops
|
||||
assert updateKeys.size() == updateEvents.size();
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
int newEvents = updateEvents.pollFirst();
|
||||
int fd = ski.channel.getFDVal();
|
||||
if (ski.isValid() && fdToKey.containsKey(fd)) {
|
||||
if (ski.isValid()) {
|
||||
int fd = ski.getFDVal();
|
||||
// add to fdToKey if needed
|
||||
SelectionKeyImpl previous = fdToKey.putIfAbsent(fd, ski);
|
||||
assert (previous == null) || (previous == ski);
|
||||
|
||||
int newEvents = ski.translateInterestOps();
|
||||
if (newEvents != ski.registeredEvents()) {
|
||||
if (newEvents == 0) {
|
||||
port_dissociate(pfd, PORT_SOURCE_FD, fd);
|
||||
@ -199,22 +188,20 @@ class EventPortSelectorImpl
|
||||
if (ski != null) {
|
||||
int rOps = getEventOps(i);
|
||||
if (selectedKeys.contains(ski)) {
|
||||
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
|
||||
if (ski.translateAndSetReadyOps(rOps)) {
|
||||
numKeysUpdated++;
|
||||
}
|
||||
} else {
|
||||
ski.channel.translateAndSetReadyOps(rOps, ski);
|
||||
ski.translateAndSetReadyOps(rOps);
|
||||
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(ski);
|
||||
numKeysUpdated++;
|
||||
}
|
||||
}
|
||||
|
||||
// re-queue key to head so that it is re-associated at
|
||||
// next select (and before other changes)
|
||||
updateEvents.addFirst(ski.registeredEvents());
|
||||
updateKeys.addFirst(ski);
|
||||
// re-queue key so it re-associated at next select
|
||||
ski.registeredEvents(0);
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
} else if (source == PORT_SOURCE_USER) {
|
||||
interrupted = true;
|
||||
@ -244,20 +231,12 @@ class EventPortSelectorImpl
|
||||
pollArray.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implRegister(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
newKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void implDereg(SelectionKeyImpl ski) throws IOException {
|
||||
assert !ski.isValid();
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
int fd = ski.channel.getFDVal();
|
||||
int fd = ski.getFDVal();
|
||||
if (fdToKey.remove(fd) != null) {
|
||||
if (ski.registeredEvents() != 0) {
|
||||
port_dissociate(pfd, PORT_SOURCE_FD, fd);
|
||||
@ -269,10 +248,9 @@ class EventPortSelectorImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putEventOps(SelectionKeyImpl ski, int events) {
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateEvents.addLast(events); // events first in case adding key fails
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
@ -23,84 +23,20 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <sys/devpoll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "jvm.h"
|
||||
#include "jlong.h"
|
||||
#include "nio.h"
|
||||
#include "nio_util.h"
|
||||
|
||||
#include "sun_nio_ch_DevPollArrayWrapper.h"
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef uint32_t caddr32_t;
|
||||
|
||||
/* /dev/poll ioctl */
|
||||
#define DPIOC (0xD0 << 8)
|
||||
#define DP_POLL (DPIOC | 1) /* poll on fds in cached in /dev/poll */
|
||||
#define DP_ISPOLLED (DPIOC | 2) /* is this fd cached in /dev/poll */
|
||||
#define DEVPOLLSIZE 1000 /* /dev/poll table size increment */
|
||||
#define POLLREMOVE 0x0800 /* Removes fd from monitored set */
|
||||
|
||||
/*
|
||||
* /dev/poll DP_POLL ioctl format
|
||||
*/
|
||||
typedef struct dvpoll {
|
||||
pollfd_t *dp_fds; /* pollfd array */
|
||||
nfds_t dp_nfds; /* num of pollfd's in dp_fds[] */
|
||||
int dp_timeout; /* time out in millisec */
|
||||
} dvpoll_t;
|
||||
|
||||
typedef struct dvpoll32 {
|
||||
caddr32_t dp_fds; /* pollfd array */
|
||||
uint32_t dp_nfds; /* num of pollfd's in dp_fds[] */
|
||||
int32_t dp_timeout; /* time out in millisec */
|
||||
} dvpoll32_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RESTARTABLE(_cmd, _result) do { \
|
||||
do { \
|
||||
_result = _cmd; \
|
||||
} while((_result == -1) && (errno == EINTR)); \
|
||||
} while(0)
|
||||
|
||||
static int
|
||||
idevpoll(jint wfd, int dpctl, struct dvpoll a)
|
||||
{
|
||||
jlong start, now;
|
||||
int remaining = a.dp_timeout;
|
||||
struct timeval t;
|
||||
int diff;
|
||||
|
||||
gettimeofday(&t, NULL);
|
||||
start = t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
|
||||
for (;;) {
|
||||
/* poll(7d) ioctl does not return remaining count */
|
||||
int res = ioctl(wfd, dpctl, &a);
|
||||
if (res < 0 && errno == EINTR) {
|
||||
if (remaining >= 0) {
|
||||
gettimeofday(&t, NULL);
|
||||
now = t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
diff = now - start;
|
||||
remaining -= diff;
|
||||
if (diff < 0 || remaining <= 0) {
|
||||
return 0;
|
||||
}
|
||||
start = now;
|
||||
a.dp_timeout = remaining;
|
||||
}
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_DevPollArrayWrapper_init(JNIEnv *env, jobject this)
|
||||
@ -153,26 +89,24 @@ Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple(JNIEnv *env, jobject this,
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
|
||||
jlong address, jint numfds,
|
||||
jlong timeout, jint wfd)
|
||||
jlong address, jint numfds,
|
||||
jlong timeout, jint wfd)
|
||||
{
|
||||
struct dvpoll a;
|
||||
void *pfd = (void *) jlong_to_ptr(address);
|
||||
int result = 0;
|
||||
int result;
|
||||
|
||||
a.dp_fds = pfd;
|
||||
a.dp_nfds = numfds;
|
||||
a.dp_timeout = (int)timeout;
|
||||
|
||||
if (timeout <= 0) { /* Indefinite or no wait */
|
||||
RESTARTABLE (ioctl(wfd, DP_POLL, &a), result);
|
||||
} else { /* Bounded wait; bounded restarts */
|
||||
result = idevpoll(wfd, DP_POLL, a);
|
||||
}
|
||||
|
||||
result = ioctl(wfd, DP_POLL, &a);
|
||||
if (result < 0) {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Error reading driver");
|
||||
return -1;
|
||||
if (errno == EINTR) {
|
||||
return IOS_INTERRUPTED;
|
||||
} else {
|
||||
JNU_ThrowIOExceptionWithLastError(env, "Error reading driver");
|
||||
return IOS_THROWN;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -60,7 +60,6 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
// pending updates, queued by putEventOps
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
private final Deque<Integer> updateEvents = new ArrayDeque<>();
|
||||
|
||||
// interrupt triggering and clearing
|
||||
private final Object interruptLock = new Object();
|
||||
@ -136,10 +135,9 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
assert Thread.holdsLock(this);
|
||||
|
||||
synchronized (updateLock) {
|
||||
assert updateKeys.size() == updateEvents.size();
|
||||
SelectionKeyImpl ski;
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
int newEvents = updateEvents.pollFirst();
|
||||
int newEvents = ski.translateInterestOps();
|
||||
if (ski.isValid()) {
|
||||
int index = ski.getIndex();
|
||||
assert index >= 0 && index < pollArraySize;
|
||||
@ -173,14 +171,14 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
int rOps = getReventOps(i);
|
||||
if (rOps != 0) {
|
||||
SelectionKeyImpl ski = pollKeys.get(i);
|
||||
assert ski.channel.getFDVal() == getDescriptor(i);
|
||||
assert ski.getFDVal() == getDescriptor(i);
|
||||
if (ski.isValid()) {
|
||||
if (selectedKeys.contains(ski)) {
|
||||
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
|
||||
if (ski.translateAndSetReadyOps(rOps)) {
|
||||
numKeysUpdated++;
|
||||
}
|
||||
} else {
|
||||
ski.channel.translateAndSetReadyOps(rOps, ski);
|
||||
ski.translateAndSetReadyOps(rOps);
|
||||
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(ski);
|
||||
numKeysUpdated++;
|
||||
@ -233,10 +231,9 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putEventOps(SelectionKeyImpl ski, int events) {
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateEvents.addLast(events); // events first in case adding key fails
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
@ -285,7 +282,7 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
|
||||
int index = pollArraySize;
|
||||
assert index > 0;
|
||||
putDescriptor(index, ski.channel.getFDVal());
|
||||
putDescriptor(index, ski.getFDVal());
|
||||
putEventOps(index, ops);
|
||||
putReventOps(index, 0);
|
||||
ski.setIndex(index);
|
||||
@ -301,7 +298,7 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
private void update(SelectionKeyImpl ski, int ops) {
|
||||
int index = ski.getIndex();
|
||||
assert index > 0 && index < pollArraySize;
|
||||
assert getDescriptor(index) == ski.channel.getFDVal();
|
||||
assert getDescriptor(index) == ski.getFDVal();
|
||||
putEventOps(index, ops);
|
||||
}
|
||||
|
||||
@ -311,7 +308,7 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
private void remove(SelectionKeyImpl ski) {
|
||||
int index = ski.getIndex();
|
||||
assert index > 0 && index < pollArraySize;
|
||||
assert getDescriptor(index) == ski.channel.getFDVal();
|
||||
assert getDescriptor(index) == ski.getFDVal();
|
||||
|
||||
// replace pollfd at index with the last pollfd in array
|
||||
int lastIndex = pollArraySize - 1;
|
||||
@ -321,7 +318,7 @@ class PollSelectorImpl extends SelectorImpl {
|
||||
int lastFd = getDescriptor(lastIndex);
|
||||
int lastOps = getEventOps(lastIndex);
|
||||
int lastRevents = getReventOps(lastIndex);
|
||||
assert lastKey.channel.getFDVal() == lastFd;
|
||||
assert lastKey.getFDVal() == lastFd;
|
||||
putDescriptor(index, lastFd);
|
||||
putEventOps(index, lastOps);
|
||||
putReventOps(index, lastRevents);
|
||||
|
@ -64,7 +64,7 @@ class PollArrayWrapper {
|
||||
|
||||
// Prepare another pollfd struct for use.
|
||||
void putEntry(int index, SelectionKeyImpl ski) {
|
||||
putDescriptor(index, ski.channel.getFDVal());
|
||||
putDescriptor(index, ski.getFDVal());
|
||||
putEventOps(index, 0);
|
||||
}
|
||||
|
||||
|
@ -83,12 +83,12 @@ class WindowsSelectorImpl extends SelectorImpl {
|
||||
return get(Integer.valueOf(desc));
|
||||
}
|
||||
private MapEntry put(SelectionKeyImpl ski) {
|
||||
return put(Integer.valueOf(ski.channel.getFDVal()), new MapEntry(ski));
|
||||
return put(Integer.valueOf(ski.getFDVal()), new MapEntry(ski));
|
||||
}
|
||||
private MapEntry remove(SelectionKeyImpl ski) {
|
||||
Integer fd = Integer.valueOf(ski.channel.getFDVal());
|
||||
Integer fd = Integer.valueOf(ski.getFDVal());
|
||||
MapEntry x = get(fd);
|
||||
if ((x != null) && (x.ski.channel == ski.channel))
|
||||
if ((x != null) && (x.ski.channel() == ski.channel()))
|
||||
return remove(fd);
|
||||
return null;
|
||||
}
|
||||
@ -114,11 +114,10 @@ class WindowsSelectorImpl extends SelectorImpl {
|
||||
private final Object interruptLock = new Object();
|
||||
private volatile boolean interruptTriggered;
|
||||
|
||||
// pending new registrations/updates, queued by implRegister and putEventOps
|
||||
// pending new registrations/updates, queued by implRegister and setEventOps
|
||||
private final Object updateLock = new Object();
|
||||
private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
|
||||
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
|
||||
private final Deque<Integer> updateEvents = new ArrayDeque<>();
|
||||
|
||||
|
||||
WindowsSelectorImpl(SelectorProvider sp) throws IOException {
|
||||
@ -204,10 +203,9 @@ class WindowsSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
// changes to interest ops
|
||||
assert updateKeys.size() == updateEvents.size();
|
||||
while ((ski = updateKeys.pollFirst()) != null) {
|
||||
int events = updateEvents.pollFirst();
|
||||
int fd = ski.channel.getFDVal();
|
||||
int events = ski.translateInterestOps();
|
||||
int fd = ski.getFDVal();
|
||||
if (ski.isValid() && fdMap.containsKey(fd)) {
|
||||
int index = ski.getIndex();
|
||||
assert index >= 0 && index < totalChannels;
|
||||
@ -408,13 +406,13 @@ class WindowsSelectorImpl extends SelectorImpl {
|
||||
|
||||
if (selectedKeys.contains(sk)) { // Key in selected set
|
||||
if (me.clearedCount != updateCount) {
|
||||
if (sk.channel.translateAndSetReadyOps(rOps, sk) &&
|
||||
if (sk.translateAndSetReadyOps(rOps) &&
|
||||
(me.updateCount != updateCount)) {
|
||||
me.updateCount = updateCount;
|
||||
numKeysUpdated++;
|
||||
}
|
||||
} else { // The readyOps have been set; now add
|
||||
if (sk.channel.translateAndUpdateReadyOps(rOps, sk) &&
|
||||
if (sk.translateAndUpdateReadyOps(rOps) &&
|
||||
(me.updateCount != updateCount)) {
|
||||
me.updateCount = updateCount;
|
||||
numKeysUpdated++;
|
||||
@ -423,14 +421,14 @@ class WindowsSelectorImpl extends SelectorImpl {
|
||||
me.clearedCount = updateCount;
|
||||
} else { // Key is not in selected set yet
|
||||
if (me.clearedCount != updateCount) {
|
||||
sk.channel.translateAndSetReadyOps(rOps, sk);
|
||||
sk.translateAndSetReadyOps(rOps);
|
||||
if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(sk);
|
||||
me.updateCount = updateCount;
|
||||
numKeysUpdated++;
|
||||
}
|
||||
} else { // The readyOps have been set; now add
|
||||
sk.channel.translateAndUpdateReadyOps(rOps, sk);
|
||||
sk.translateAndUpdateReadyOps(rOps);
|
||||
if ((sk.nioReadyOps() & sk.nioInterestOps()) != 0) {
|
||||
selectedKeys.add(sk);
|
||||
me.updateCount = updateCount;
|
||||
@ -613,10 +611,9 @@ class WindowsSelectorImpl extends SelectorImpl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putEventOps(SelectionKeyImpl ski, int events) {
|
||||
public void setEventOps(SelectionKeyImpl ski) {
|
||||
ensureOpen();
|
||||
synchronized (updateLock) {
|
||||
updateEvents.addLast(events); // events first in case adding key fails
|
||||
updateKeys.addLast(ski);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user