--- a/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java Thu Apr 25 09:12:40 2019 +0200
+++ b/src/java.base/unix/classes/sun/nio/ch/SinkChannelImpl.java Thu Apr 25 10:41:49 2019 +0100
@@ -35,6 +35,7 @@
import java.nio.channels.SelectionKey;
import java.nio.channels.spi.SelectorProvider;
import java.util.Objects;
+import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
class SinkChannelImpl
@@ -53,7 +54,8 @@
// Lock held by any thread that modifies the state fields declared below
// DO NOT invoke a blocking I/O operation while holding this lock!
- private final Object stateLock = new Object();
+ private final ReentrantLock stateLock = new ReentrantLock();
+ private final Condition stateCondition = stateLock.newCondition();
// -- The following fields are protected by stateLock
@@ -95,15 +97,19 @@
boolean blocking;
// set state to ST_CLOSING
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
assert state < ST_CLOSING;
state = ST_CLOSING;
blocking = isBlocking();
+ } finally {
+ stateLock.unlock();
}
// wait for any outstanding write to complete
if (blocking) {
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
assert state == ST_CLOSING;
long th = thread;
if (th != 0) {
@@ -113,12 +119,14 @@
// wait for write operation to end
while (thread != 0) {
try {
- stateLock.wait();
+ stateCondition.await();
} catch (InterruptedException e) {
interrupted = true;
}
}
}
+ } finally {
+ stateLock.unlock();
}
} else {
// non-blocking mode: wait for write to complete
@@ -127,9 +135,12 @@
}
// set state to ST_KILLPENDING
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
assert state == ST_CLOSING;
state = ST_KILLPENDING;
+ } finally {
+ stateLock.unlock();
}
// close socket if not registered with Selector
@@ -143,12 +154,15 @@
@Override
public void kill() throws IOException {
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
assert thread == 0;
if (state == ST_KILLPENDING) {
state = ST_KILLED;
nd.close(fd);
}
+ } finally {
+ stateLock.unlock();
}
}
@@ -156,8 +170,11 @@
protected void implConfigureBlocking(boolean block) throws IOException {
writeLock.lock();
try {
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
IOUtil.configureBlocking(fd, block);
+ } finally {
+ stateLock.unlock();
}
} finally {
writeLock.unlock();
@@ -212,11 +229,14 @@
// set hook for Thread.interrupt
begin();
}
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
if (!isOpen())
throw new ClosedChannelException();
if (blocking)
thread = NativeThread.current();
+ } finally {
+ stateLock.unlock();
}
}
@@ -230,12 +250,15 @@
throws AsynchronousCloseException
{
if (blocking) {
- synchronized (stateLock) {
+ stateLock.lock();
+ try {
thread = 0;
// notify any thread waiting in implCloseSelectableChannel
if (state == ST_CLOSING) {
- stateLock.notifyAll();
+ stateCondition.signalAll();
}
+ } finally {
+ stateLock.unlock();
}
// remove hook for Thread.interrupt
end(completed);
@@ -252,9 +275,13 @@
int n = 0;
try {
beginWrite(blocking);
- do {
- n = IOUtil.write(fd, src, -1, nd);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
+ n = IOUtil.write(fd, src, -1, nd);
+ if (blocking) {
+ while (IOStatus.okayToRetry(n) && isOpen()) {
+ park(Net.POLLOUT);
+ n = IOUtil.write(fd, src, -1, nd);
+ }
+ }
} finally {
endWrite(blocking, n > 0);
assert IOStatus.check(n);
@@ -275,9 +302,13 @@
long n = 0;
try {
beginWrite(blocking);
- do {
- n = IOUtil.write(fd, srcs, offset, length, nd);
- } while ((n == IOStatus.INTERRUPTED) && isOpen());
+ n = IOUtil.write(fd, srcs, offset, length, nd);
+ if (blocking) {
+ while (IOStatus.okayToRetry(n) && isOpen()) {
+ park(Net.POLLOUT);
+ n = IOUtil.write(fd, srcs, offset, length, nd);
+ }
+ }
} finally {
endWrite(blocking, n > 0);
assert IOStatus.check(n);