8199611: (se) Minor selector implementation clean-up

Reviewed-by: clanger, redestad, bpb
This commit is contained in:
Alan Bateman 2018-03-15 10:47:58 +00:00
parent 8994d5ad0e
commit 3a7f72200c
15 changed files with 238 additions and 249 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -58,6 +58,7 @@ class KQueue {
// flags
static final int EV_ADD = 0x0001;
static final int EV_DELETE = 0x0002;
static final int EV_ONESHOT = 0x0010;
static final int EV_CLEAR = 0x0020;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -66,20 +66,18 @@ class KQueueArrayWrapper {
static final int NUM_KEVENTS = 128;
// Are we in a 64-bit VM?
static boolean is64bit = false;
static boolean is64bit;
// The kevent array (used for outcoming events only)
private AllocatedNativeObject keventArray = null;
private long keventArrayAddress;
private final AllocatedNativeObject keventArray;
private final long keventArrayAddress;
// The kqueue fd
private int kq = -1;
private final int kq;
// The fd of the interrupt line going out
private int outgoingInterruptFD;
private final int outgoingInterruptFD;
// The fd of the interrupt line coming in
private int incomingInterruptFD;
static {
IOUtil.load();
@ -89,11 +87,13 @@ class KQueueArrayWrapper {
is64bit = "64".equals(datamodel);
}
KQueueArrayWrapper() {
KQueueArrayWrapper(int fd0, int fd1) throws IOException {
int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
keventArray = new AllocatedNativeObject(allocationSize, true);
keventArrayAddress = keventArray.address();
kq = init();
register0(kq, fd0, 1, 0);
outgoingInterruptFD = fd1;
}
// Used to update file description registrations
@ -108,12 +108,6 @@ class KQueueArrayWrapper {
private LinkedList<Update> updateList = new LinkedList<Update>();
void initInterrupt(int fd0, int fd1) {
outgoingInterruptFD = fd1;
incomingInterruptFD = fd0;
register0(kq, fd0, 1, 0);
}
int getReventOps(int index) {
int result = 0;
int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
@ -137,11 +131,11 @@ class KQueueArrayWrapper {
* to return an int. Hence read the 8 bytes but return as an int.
*/
if (is64bit) {
long fd = keventArray.getLong(offset);
assert fd <= Integer.MAX_VALUE;
return (int) fd;
long fd = keventArray.getLong(offset);
assert fd <= Integer.MAX_VALUE;
return (int) fd;
} else {
return keventArray.getInt(offset);
return keventArray.getInt(offset);
}
}
@ -168,7 +162,7 @@ class KQueueArrayWrapper {
void updateRegistrations() {
synchronized (updateList) {
Update u = null;
Update u;
while ((u = updateList.poll()) != null) {
SelChImpl ch = u.channel;
if (!ch.isOpen())
@ -179,22 +173,14 @@ class KQueueArrayWrapper {
}
}
void close() throws IOException {
if (keventArray != null) {
keventArray.free();
keventArray = null;
}
if (kq >= 0) {
FileDispatcherImpl.closeIntFD(kq);
kq = -1;
}
FileDispatcherImpl.closeIntFD(kq);
keventArray.free();
}
int poll(long timeout) {
updateRegistrations();
int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
return updated;
return kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
}
void interrupt() {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,39 +26,38 @@
/*
* KQueueSelectorImpl.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollSelectorImpl
*/
package sun.nio.ch;
import java.io.IOException;
import java.io.FileDescriptor;
import java.nio.channels.*;
import java.nio.channels.spi.*;
import java.util.*;
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.HashMap;
import java.util.Iterator;
class KQueueSelectorImpl
extends SelectorImpl
{
// File descriptors used for interrupt
protected int fd0;
protected int fd1;
private final int fd0;
private final int fd1;
// The kqueue manipulator
KQueueArrayWrapper kqueueWrapper;
// Count of registered descriptors (including interrupt)
private int totalChannels;
private final KQueueArrayWrapper kqueueWrapper;
// Map from a file descriptor to an entry containing the selection key
private HashMap<Integer,MapEntry> fdMap;
private final HashMap<Integer, MapEntry> fdMap;
// True if this Selector has been closed
private boolean closed = false;
private boolean closed;
// Lock for interrupt triggering and clearing
private Object interruptLock = new Object();
private boolean interruptTriggered = false;
private final Object interruptLock = new Object();
private boolean interruptTriggered;
// used by updateSelectedKeys to handle cases where the same file
// descriptor is polled by more than one filter
@ -78,16 +77,14 @@ class KQueueSelectorImpl
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
KQueueSelectorImpl(SelectorProvider sp) {
KQueueSelectorImpl(SelectorProvider sp) throws IOException {
super(sp);
long fds = IOUtil.makePipe(false);
fd0 = (int)(fds >>> 32);
fd1 = (int)fds;
try {
kqueueWrapper = new KQueueArrayWrapper();
kqueueWrapper.initInterrupt(fd0, fd1);
kqueueWrapper = new KQueueArrayWrapper(fd0, fd1);
fdMap = new HashMap<>();
totalChannels = 1;
} catch (Throwable t) {
try {
FileDispatcherImpl.closeIntFD(fd0);
@ -103,22 +100,26 @@ class KQueueSelectorImpl
}
}
private void ensureOpen() {
if (closed)
throw new ClosedSelectorException();
}
@Override
protected int doSelect(long timeout)
throws IOException
{
int entries = 0;
if (closed)
throw new ClosedSelectorException();
ensureOpen();
int numEntries;
processDeregisterQueue();
try {
begin();
entries = kqueueWrapper.poll(timeout);
numEntries = kqueueWrapper.poll(timeout);
} finally {
end();
}
processDeregisterQueue();
return updateSelectedKeys(entries);
return updateSelectedKeys(numEntries);
}
/**
@ -126,7 +127,7 @@ class KQueueSelectorImpl
* Add the ready keys to the selected key set.
* If the interrupt fd has been selected, drain it and clear the interrupt.
*/
private int updateSelectedKeys(int entries)
private int updateSelectedKeys(int numEntries)
throws IOException
{
int numKeysUpdated = 0;
@ -139,14 +140,12 @@ class KQueueSelectorImpl
// second or subsequent event.
updateCount++;
for (int i = 0; i < entries; i++) {
for (int i = 0; i < numEntries; i++) {
int nextFD = kqueueWrapper.getDescriptor(i);
if (nextFD == fd0) {
interrupted = true;
} else {
MapEntry me = fdMap.get(Integer.valueOf(nextFD));
// entry is null in the case of an interrupt
if (me != null) {
int rOps = kqueueWrapper.getReventOps(i);
SelectionKeyImpl ski = me.ski;
@ -175,16 +174,12 @@ class KQueueSelectorImpl
}
if (interrupted) {
// Clear the wakeup pipe
synchronized (interruptLock) {
IOUtil.drain(fd0);
interruptTriggered = false;
}
clearInterrupt();
}
return numKeysUpdated;
}
@Override
protected void implClose() throws IOException {
if (!closed) {
closed = true;
@ -194,62 +189,51 @@ class KQueueSelectorImpl
interruptTriggered = true;
}
kqueueWrapper.close();
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
if (kqueueWrapper != null) {
kqueueWrapper.close();
kqueueWrapper = null;
selectedKeys = null;
// 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();
}
totalChannels = 0;
// 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();
}
fd0 = -1;
fd1 = -1;
}
}
@Override
protected void implRegister(SelectionKeyImpl ski) {
if (closed)
throw new ClosedSelectorException();
ensureOpen();
int fd = IOUtil.fdVal(ski.channel.getFD());
fdMap.put(Integer.valueOf(fd), new MapEntry(ski));
totalChannels++;
keys.add(ski);
}
@Override
protected void implDereg(SelectionKeyImpl ski) throws IOException {
int fd = ski.channel.getFDVal();
fdMap.remove(Integer.valueOf(fd));
kqueueWrapper.release(ski.channel);
totalChannels--;
keys.remove(ski);
selectedKeys.remove(ski);
deregister((AbstractSelectionKey)ski);
deregister(ski);
SelectableChannel selch = ski.channel();
if (!selch.isOpen() && !selch.isRegistered())
((SelChImpl)selch).kill();
}
@Override
public void putEventOps(SelectionKeyImpl ski, int ops) {
if (closed)
throw new ClosedSelectorException();
ensureOpen();
kqueueWrapper.setInterest(ski.channel, ops);
}
@Override
public Selector wakeup() {
synchronized (interruptLock) {
if (!interruptTriggered) {
@ -259,4 +243,11 @@ class KQueueSelectorImpl
}
return this;
}
private void clearInterrupt() throws IOException {
synchronized (interruptLock) {
IOUtil.drain(fd0);
interruptTriggered = false;
}
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -36,7 +36,7 @@ import java.nio.channels.*;
import java.nio.channels.spi.*;
public class KQueueSelectorProvider
extends SelectorProviderImpl
extends SelectorProviderImpl
{
public AbstractSelector openSelector() throws IOException {
return new KQueueSelectorImpl(this);