8199120: (so) SocketChannelImpl read/write don't need stateLock when channel is configured non-blocking

Reviewed-by: bpb
This commit is contained in:
Alan Bateman 2018-03-07 07:20:38 +00:00
parent 61aa187aaf
commit c37c87b388

View file

@ -148,12 +148,37 @@ class SocketChannelImpl
} }
} }
// @throws ClosedChannelException if channel is closed /**
* Checks that the channel is open.
*
* @throws ClosedChannelException if channel is closed (or closing)
*/
private void ensureOpen() throws ClosedChannelException { private void ensureOpen() throws ClosedChannelException {
if (!isOpen()) if (!isOpen())
throw new ClosedChannelException(); throw new ClosedChannelException();
} }
/**
* Checks that the channel is open and connected.
*
* @apiNote This method uses the "state" field to check if the channel is
* open. It should never be used in conjuncion with isOpen or ensureOpen
* as these methods check AbstractInterruptibleChannel's closed field - that
* field is set before implCloseSelectableChannel is called and so before
* the state is changed.
*
* @throws ClosedChannelException if channel is closed (or closing)
* @throws NotYetConnectedException if open and not connected
*/
private void ensureOpenAndConnected() throws ClosedChannelException {
int state = this.state;
if (state < ST_CONNECTED) {
throw new NotYetConnectedException();
} else if (state > ST_CONNECTED) {
throw new ClosedChannelException();
}
}
@Override @Override
public Socket socket() { public Socket socket() {
synchronized (stateLock) { synchronized (stateLock) {
@ -275,14 +300,15 @@ class SocketChannelImpl
if (blocking) { if (blocking) {
// set hook for Thread.interrupt // set hook for Thread.interrupt
begin(); begin();
}
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpenAndConnected();
if (state != ST_CONNECTED) // record thread so it can be signalled if needed
throw new NotYetConnectedException();
if (blocking)
readerThread = NativeThread.current(); readerThread = NativeThread.current();
} }
} else {
ensureOpenAndConnected();
}
} }
/** /**
@ -385,16 +411,17 @@ class SocketChannelImpl
if (blocking) { if (blocking) {
// set hook for Thread.interrupt // set hook for Thread.interrupt
begin(); begin();
}
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpenAndConnected();
if (isOutputClosed) if (isOutputClosed)
throw new ClosedChannelException(); throw new ClosedChannelException();
if (state != ST_CONNECTED) // record thread so it can be signalled if needed
throw new NotYetConnectedException();
if (blocking)
writerThread = NativeThread.current(); writerThread = NativeThread.current();
} }
} else {
ensureOpenAndConnected();
}
} }
/** /**
@ -612,10 +639,12 @@ class SocketChannelImpl
NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort()); NetHooks.beforeTcpConnect(fd, isa.getAddress(), isa.getPort());
remoteAddress = isa; remoteAddress = isa;
if (blocking) if (blocking) {
// record thread so it can be signalled if needed
readerThread = NativeThread.current(); readerThread = NativeThread.current();
} }
} }
}
/** /**
* Marks the end of a connect operation that may have blocked. * Marks the end of a connect operation that may have blocked.
@ -695,10 +724,12 @@ class SocketChannelImpl
ensureOpen(); ensureOpen();
if (state != ST_CONNECTIONPENDING) if (state != ST_CONNECTIONPENDING)
throw new NoConnectionPendingException(); throw new NoConnectionPendingException();
if (blocking) if (blocking) {
// record thread so it can be signalled if needed
readerThread = NativeThread.current(); readerThread = NativeThread.current();
} }
} }
}
/** /**
* Marks the end of a finishConnect operation that may have blocked. * Marks the end of a finishConnect operation that may have blocked.