mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8201315: (se) Allow SelectableChannel.register to be invoked while selection operation is in progress
Reviewed-by: bpb
This commit is contained in:
parent
76590dc009
commit
33b921f25d
6 changed files with 244 additions and 142 deletions
|
@ -108,7 +108,7 @@ public abstract class AbstractSelectableChannel
|
|||
if (keys[i] == null)
|
||||
break;
|
||||
} else if (keys == null) {
|
||||
keys = new SelectionKey[3];
|
||||
keys = new SelectionKey[2];
|
||||
} else {
|
||||
// Grow key array
|
||||
int n = keys.length * 2;
|
||||
|
@ -123,14 +123,14 @@ public abstract class AbstractSelectableChannel
|
|||
}
|
||||
|
||||
private SelectionKey findKey(Selector sel) {
|
||||
synchronized (keyLock) {
|
||||
if (keys == null)
|
||||
return null;
|
||||
for (int i = 0; i < keys.length; i++)
|
||||
if ((keys[i] != null) && (keys[i].selector() == sel))
|
||||
return keys[i];
|
||||
assert Thread.holdsLock(keyLock);
|
||||
if (keys == null)
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < keys.length; i++)
|
||||
if ((keys[i] != null) && (keys[i].selector() == sel))
|
||||
return keys[i];
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
void removeKey(SelectionKey k) { // package-private
|
||||
|
@ -166,7 +166,9 @@ public abstract class AbstractSelectableChannel
|
|||
}
|
||||
|
||||
public final SelectionKey keyFor(Selector sel) {
|
||||
return findKey(sel);
|
||||
synchronized (keyLock) {
|
||||
return findKey(sel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -195,32 +197,31 @@ public abstract class AbstractSelectableChannel
|
|||
*
|
||||
* @throws IllegalArgumentException {@inheritDoc}
|
||||
*/
|
||||
public final SelectionKey register(Selector sel, int ops,
|
||||
Object att)
|
||||
public final SelectionKey register(Selector sel, int ops, Object att)
|
||||
throws ClosedChannelException
|
||||
{
|
||||
if ((ops & ~validOps()) != 0)
|
||||
throw new IllegalArgumentException();
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
synchronized (regLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
if ((ops & ~validOps()) != 0)
|
||||
throw new IllegalArgumentException();
|
||||
if (isBlocking())
|
||||
throw new IllegalBlockingModeException();
|
||||
SelectionKey k = findKey(sel);
|
||||
if (k != null) {
|
||||
k.interestOps(ops);
|
||||
k.attach(att);
|
||||
}
|
||||
if (k == null) {
|
||||
// New registration
|
||||
synchronized (keyLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
synchronized (keyLock) {
|
||||
// re-check if channel has been closed
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
SelectionKey k = findKey(sel);
|
||||
if (k != null) {
|
||||
k.attach(att);
|
||||
k.interestOps(ops);
|
||||
} else {
|
||||
// New registration
|
||||
k = ((AbstractSelector)sel).register(this, ops, att);
|
||||
addKey(k);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,12 +240,20 @@ public abstract class AbstractSelectableChannel
|
|||
*/
|
||||
protected final void implCloseChannel() throws IOException {
|
||||
implCloseSelectableChannel();
|
||||
|
||||
// clone keys to avoid calling cancel when holding keyLock
|
||||
SelectionKey[] copyOfKeys = null;
|
||||
synchronized (keyLock) {
|
||||
int count = (keys == null) ? 0 : keys.length;
|
||||
for (int i = 0; i < count; i++) {
|
||||
SelectionKey k = keys[i];
|
||||
if (k != null)
|
||||
k.cancel();
|
||||
if (keys != null) {
|
||||
copyOfKeys = keys.clone();
|
||||
}
|
||||
}
|
||||
|
||||
if (copyOfKeys != null) {
|
||||
for (SelectionKey k : copyOfKeys) {
|
||||
if (k != null) {
|
||||
k.cancel(); // invalidate and adds key to cancelledKey set
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue