mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8196787: (ch) Moving network channels to use j.u.c locks
Reviewed-by: prappo, rriggs
This commit is contained in:
parent
6ff900807d
commit
8deac7d09b
10 changed files with 270 additions and 126 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
|
@ -27,11 +27,32 @@ package sun.nio.ch;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.PortUnreachableException;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.MembershipKey;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.UnsupportedAddressTypeException;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.net.ResourceManager;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
|
@ -67,10 +88,10 @@ class DatagramChannelImpl
|
|||
private int cachedSenderPort;
|
||||
|
||||
// Lock held by current reading or connecting thread
|
||||
private final Object readLock = new Object();
|
||||
private final ReentrantLock readLock = new ReentrantLock();
|
||||
|
||||
// Lock held by current writing or connecting thread
|
||||
private final Object writeLock = new Object();
|
||||
private final ReentrantLock writeLock = new ReentrantLock();
|
||||
|
||||
// Lock held by any thread that modifies the state fields declared below
|
||||
// DO NOT invoke a blocking I/O operation while holding this lock!
|
||||
|
@ -328,7 +349,8 @@ class DatagramChannelImpl
|
|||
public SocketAddress receive(ByteBuffer dst) throws IOException {
|
||||
if (dst.isReadOnly())
|
||||
throw new IllegalArgumentException("Read-only buffer");
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
ensureOpen();
|
||||
// Socket was not bound before attempting receive
|
||||
if (localAddress() == null)
|
||||
|
@ -348,6 +370,8 @@ class DatagramChannelImpl
|
|||
if (n == IOStatus.UNAVAILABLE)
|
||||
return null;
|
||||
} else {
|
||||
// Cannot receive into user's buffer when running with a
|
||||
// security manager and not connected
|
||||
bb = Util.getTemporaryDirectBuffer(dst.remaining());
|
||||
for (;;) {
|
||||
do {
|
||||
|
@ -379,6 +403,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -425,7 +451,8 @@ class DatagramChannelImpl
|
|||
if (src == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureOpen();
|
||||
InetSocketAddress isa = Net.checkAddress(target);
|
||||
InetAddress ia = isa.getAddress();
|
||||
|
@ -474,6 +501,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,7 +563,8 @@ class DatagramChannelImpl
|
|||
public int read(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -555,6 +585,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,7 +595,8 @@ class DatagramChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -584,13 +617,16 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int write(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -611,6 +647,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -619,7 +657,8 @@ class DatagramChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (!isConnected())
|
||||
|
@ -640,6 +679,8 @@ class DatagramChannelImpl
|
|||
end((n > 0) || (n == IOStatus.UNAVAILABLE));
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -661,8 +702,10 @@ class DatagramChannelImpl
|
|||
|
||||
@Override
|
||||
public DatagramChannel bind(SocketAddress local) throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpen();
|
||||
if (localAddress != null)
|
||||
|
@ -692,7 +735,11 @@ class DatagramChannelImpl
|
|||
Net.bind(family, fd, isa.getAddress(), isa.getPort());
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -714,8 +761,10 @@ class DatagramChannelImpl
|
|||
|
||||
@Override
|
||||
public DatagramChannel connect(SocketAddress sa) throws IOException {
|
||||
synchronized(readLock) {
|
||||
synchronized(writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
ensureOpenAndUnconnected();
|
||||
InetSocketAddress isa = Net.checkAddress(sa);
|
||||
|
@ -759,14 +808,20 @@ class DatagramChannelImpl
|
|||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public DatagramChannel disconnect() throws IOException {
|
||||
synchronized(readLock) {
|
||||
synchronized(writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
if (!isConnected() || !isOpen())
|
||||
return this;
|
||||
|
@ -783,7 +838,11 @@ class DatagramChannelImpl
|
|||
// refresh local address
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -1087,7 +1146,8 @@ class DatagramChannelImpl
|
|||
int poll(int events, long timeout) throws IOException {
|
||||
assert Thread.holdsLock(blockingLock()) && !isBlocking();
|
||||
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
try {
|
||||
begin();
|
||||
|
@ -1102,6 +1162,8 @@ class DatagramChannelImpl
|
|||
end(n > 0);
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
|
@ -78,7 +78,7 @@ public class IOUtil {
|
|||
src.position(pos);
|
||||
|
||||
int n = writeFromNativeBuffer(fd, bb, position,
|
||||
directIO, alignment, nd);
|
||||
directIO, alignment, nd);
|
||||
if (n > 0) {
|
||||
// now update src
|
||||
src.position(pos + n);
|
||||
|
@ -161,8 +161,7 @@ public class IOUtil {
|
|||
if (!(buf instanceof DirectBuffer)) {
|
||||
ByteBuffer shadow;
|
||||
if (directIO)
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem,
|
||||
alignment);
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
|
||||
else
|
||||
shadow = Util.getTemporaryDirectBuffer(rem);
|
||||
shadow.put(buf);
|
||||
|
@ -241,8 +240,7 @@ public class IOUtil {
|
|||
int rem = dst.remaining();
|
||||
if (directIO) {
|
||||
Util.checkRemainingBufferSizeAligned(rem, alignment);
|
||||
bb = Util.getTemporaryAlignedDirectBuffer(rem,
|
||||
alignment);
|
||||
bb = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
|
||||
} else {
|
||||
bb = Util.getTemporaryDirectBuffer(rem);
|
||||
}
|
||||
|
@ -277,8 +275,7 @@ public class IOUtil {
|
|||
return 0;
|
||||
int n = 0;
|
||||
if (position != -1) {
|
||||
n = nd.pread(fd, ((DirectBuffer)bb).address() + pos,
|
||||
rem, position);
|
||||
n = nd.pread(fd, ((DirectBuffer)bb).address() + pos, rem, position);
|
||||
} else {
|
||||
n = nd.read(fd, ((DirectBuffer)bb).address() + pos, rem);
|
||||
}
|
||||
|
@ -332,8 +329,7 @@ public class IOUtil {
|
|||
if (!(buf instanceof DirectBuffer)) {
|
||||
ByteBuffer shadow;
|
||||
if (directIO) {
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem,
|
||||
alignment);
|
||||
shadow = Util.getTemporaryAlignedDirectBuffer(rem, alignment);
|
||||
} else {
|
||||
shadow = Util.getTemporaryDirectBuffer(rem);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
|
@ -27,10 +27,25 @@ package sun.nio.ch;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NotYetBoundException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.net.NetHooks;
|
||||
|
||||
/**
|
||||
|
@ -56,7 +71,7 @@ class ServerSocketChannelImpl
|
|||
private volatile long thread;
|
||||
|
||||
// Lock held by thread currently blocked in this channel
|
||||
private final Object lock = new Object();
|
||||
private final ReentrantLock acceptLock = new ReentrantLock();
|
||||
|
||||
// Lock held by any thread that modifies the state fields declared below
|
||||
// DO NOT invoke a blocking I/O operation while holding this lock!
|
||||
|
@ -77,7 +92,7 @@ class ServerSocketChannelImpl
|
|||
private boolean isReuseAddress;
|
||||
|
||||
// Our socket adaptor, if any
|
||||
ServerSocket socket;
|
||||
private ServerSocket socket;
|
||||
|
||||
// -- End of fields protected by stateLock
|
||||
|
||||
|
@ -211,7 +226,8 @@ class ServerSocketChannelImpl
|
|||
|
||||
@Override
|
||||
public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
|
||||
synchronized (lock) {
|
||||
acceptLock.lock();
|
||||
try {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
if (isBound())
|
||||
|
@ -227,12 +243,15 @@ class ServerSocketChannelImpl
|
|||
synchronized (stateLock) {
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
acceptLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public SocketChannel accept() throws IOException {
|
||||
synchronized (lock) {
|
||||
acceptLock.lock();
|
||||
try {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
if (!isBound())
|
||||
|
@ -278,6 +297,8 @@ class ServerSocketChannelImpl
|
|||
}
|
||||
return sc;
|
||||
|
||||
} finally {
|
||||
acceptLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -353,7 +374,8 @@ class ServerSocketChannelImpl
|
|||
int poll(int events, long timeout) throws IOException {
|
||||
assert Thread.holdsLock(blockingLock()) && !isBlocking();
|
||||
|
||||
synchronized (lock) {
|
||||
acceptLock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
try {
|
||||
begin();
|
||||
|
@ -368,6 +390,8 @@ class ServerSocketChannelImpl
|
|||
end(n > 0);
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
acceptLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 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
|
||||
|
@ -27,11 +27,30 @@ package sun.nio.ch;
|
|||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketOption;
|
||||
import java.net.StandardProtocolFamily;
|
||||
import java.net.StandardSocketOptions;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.*;
|
||||
import java.nio.channels.spi.*;
|
||||
import java.util.*;
|
||||
import java.nio.channels.AlreadyBoundException;
|
||||
import java.nio.channels.AlreadyConnectedException;
|
||||
import java.nio.channels.AsynchronousCloseException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.ConnectionPendingException;
|
||||
import java.nio.channels.NoConnectionPendingException;
|
||||
import java.nio.channels.NotYetConnectedException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.spi.SelectorProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sun.net.NetHooks;
|
||||
import sun.net.ext.ExtendedSocketOptions;
|
||||
|
||||
|
@ -59,10 +78,10 @@ class SocketChannelImpl
|
|||
private volatile long writerThread;
|
||||
|
||||
// Lock held by current reading or connecting thread
|
||||
private final Object readLock = new Object();
|
||||
private final ReentrantLock readLock = new ReentrantLock();
|
||||
|
||||
// Lock held by current writing or connecting thread
|
||||
private final Object writeLock = new Object();
|
||||
private final ReentrantLock writeLock = new ReentrantLock();
|
||||
|
||||
// Lock held by any thread that modifies the state fields declared below
|
||||
// DO NOT invoke a blocking I/O operation while holding this lock!
|
||||
|
@ -89,7 +108,6 @@ class SocketChannelImpl
|
|||
// Input/Output open
|
||||
private boolean isInputOpen = true;
|
||||
private boolean isOutputOpen = true;
|
||||
private boolean readyToConnect = false;
|
||||
|
||||
// Socket adaptor, created on demand
|
||||
private Socket socket;
|
||||
|
@ -298,7 +316,8 @@ class SocketChannelImpl
|
|||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
if (!ensureReadOpen())
|
||||
return -1;
|
||||
int n = 0;
|
||||
|
@ -418,6 +437,8 @@ class SocketChannelImpl
|
|||
assert IOStatus.check(n);
|
||||
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -426,7 +447,8 @@ class SocketChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > dsts.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
if (!ensureReadOpen())
|
||||
return -1;
|
||||
long n = 0;
|
||||
|
@ -453,13 +475,16 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public int write(ByteBuffer buf) throws IOException {
|
||||
if (buf == null)
|
||||
throw new NullPointerException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureWriteOpen();
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -484,6 +509,8 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,7 +519,8 @@ class SocketChannelImpl
|
|||
{
|
||||
if ((offset < 0) || (length < 0) || (offset > srcs.length - length))
|
||||
throw new IndexOutOfBoundsException();
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureWriteOpen();
|
||||
long n = 0;
|
||||
try {
|
||||
|
@ -517,12 +545,15 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// package-private
|
||||
int sendOutOfBandData(byte b) throws IOException {
|
||||
synchronized (writeLock) {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureWriteOpen();
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -547,6 +578,8 @@ class SocketChannelImpl
|
|||
}
|
||||
assert IOStatus.check(n);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,8 +601,10 @@ class SocketChannelImpl
|
|||
|
||||
@Override
|
||||
public SocketChannel bind(SocketAddress local) throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
@ -587,7 +622,11 @@ class SocketChannelImpl
|
|||
Net.bind(fd, isa.getAddress(), isa.getPort());
|
||||
localAddress = Net.localAddress(fd);
|
||||
}
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
@ -616,14 +655,16 @@ class SocketChannelImpl
|
|||
}
|
||||
|
||||
public boolean connect(SocketAddress sa) throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
ensureOpenAndUnconnected();
|
||||
InetSocketAddress isa = Net.checkAddress(sa);
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null)
|
||||
sm.checkConnect(isa.getAddress().getHostAddress(),
|
||||
isa.getPort());
|
||||
isa.getPort());
|
||||
synchronized (blockingLock()) {
|
||||
int n = 0;
|
||||
try {
|
||||
|
@ -636,8 +677,8 @@ class SocketChannelImpl
|
|||
// notify hook only if unbound
|
||||
if (localAddress == null) {
|
||||
NetHooks.beforeTcpConnect(fd,
|
||||
isa.getAddress(),
|
||||
isa.getPort());
|
||||
isa.getAddress(),
|
||||
isa.getPort());
|
||||
}
|
||||
readerThread = NativeThread.current();
|
||||
}
|
||||
|
@ -646,10 +687,9 @@ class SocketChannelImpl
|
|||
if (ia.isAnyLocalAddress())
|
||||
ia = InetAddress.getLocalHost();
|
||||
n = Net.connect(fd,
|
||||
ia,
|
||||
isa.getPort());
|
||||
if ( (n == IOStatus.INTERRUPTED)
|
||||
&& isOpen())
|
||||
ia,
|
||||
isa.getPort());
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
@ -686,13 +726,19 @@ class SocketChannelImpl
|
|||
}
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean finishConnect() throws IOException {
|
||||
synchronized (readLock) {
|
||||
synchronized (writeLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
writeLock.lock();
|
||||
try {
|
||||
synchronized (stateLock) {
|
||||
if (!isOpen())
|
||||
throw new ClosedChannelException();
|
||||
|
@ -714,24 +760,20 @@ class SocketChannelImpl
|
|||
}
|
||||
if (!isBlocking()) {
|
||||
for (;;) {
|
||||
n = checkConnect(fd, false,
|
||||
readyToConnect);
|
||||
if ( (n == IOStatus.INTERRUPTED)
|
||||
&& isOpen())
|
||||
n = checkConnect(fd, false);
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
n = checkConnect(fd, true,
|
||||
readyToConnect);
|
||||
n = checkConnect(fd, true);
|
||||
if (n == 0) {
|
||||
// Loop in case of
|
||||
// spurious notifications
|
||||
continue;
|
||||
}
|
||||
if ( (n == IOStatus.INTERRUPTED)
|
||||
&& isOpen())
|
||||
if ((n == IOStatus.INTERRUPTED) && isOpen())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
@ -769,7 +811,11 @@ class SocketChannelImpl
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
writeLock.unlock();
|
||||
}
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -903,9 +949,6 @@ class SocketChannelImpl
|
|||
if ((ops & (Net.POLLERR | Net.POLLHUP)) != 0) {
|
||||
newOps = intOps;
|
||||
sk.nioReadyOps(newOps);
|
||||
// No need to poll again in checkConnect,
|
||||
// the error will be detected there
|
||||
readyToConnect = true;
|
||||
return (newOps & ~oldOps) != 0;
|
||||
}
|
||||
|
||||
|
@ -918,7 +961,6 @@ class SocketChannelImpl
|
|||
((intOps & SelectionKey.OP_CONNECT) != 0) &&
|
||||
((state == ST_UNCONNECTED) || (state == ST_PENDING))) {
|
||||
newOps |= SelectionKey.OP_CONNECT;
|
||||
readyToConnect = true;
|
||||
}
|
||||
|
||||
if (((ops & Net.POLLOUT) != 0) &&
|
||||
|
@ -942,7 +984,8 @@ class SocketChannelImpl
|
|||
int poll(int events, long timeout) throws IOException {
|
||||
assert Thread.holdsLock(blockingLock()) && !isBlocking();
|
||||
|
||||
synchronized (readLock) {
|
||||
readLock.lock();
|
||||
try {
|
||||
int n = 0;
|
||||
try {
|
||||
begin();
|
||||
|
@ -957,6 +1000,8 @@ class SocketChannelImpl
|
|||
end(n > 0);
|
||||
}
|
||||
return n;
|
||||
} finally {
|
||||
readLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1024,8 +1069,7 @@ class SocketChannelImpl
|
|||
|
||||
// -- Native methods --
|
||||
|
||||
private static native int checkConnect(FileDescriptor fd,
|
||||
boolean block, boolean ready)
|
||||
private static native int checkConnect(FileDescriptor fd, boolean block)
|
||||
throws IOException;
|
||||
|
||||
private static native int sendOutOfBandData(FileDescriptor fd, byte data)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue