提交 73e6667c 编写于 作者: A alanb

8196956: (ch) More channels cleanup

8231795: Enhance datagram socket support
Reviewed-by: rriggs, prappo, bpb
上级 e5e7de4c
...@@ -121,7 +121,7 @@ public abstract class SelectableChannel ...@@ -121,7 +121,7 @@ public abstract class SelectableChannel
// keySet, may be empty but is never null, typ. a tiny array // keySet, may be empty but is never null, typ. a tiny array
// boolean isRegistered, protected by key set // boolean isRegistered, protected by key set
// regLock, lock object to prevent duplicate registrations // regLock, lock object to prevent duplicate registrations
// boolean isBlocking, protected by regLock // blocking mode, protected by regLock
/** /**
* Tells whether or not this channel is currently registered with any * Tells whether or not this channel is currently registered with any
......
/* /*
* Copyright (c) 2000, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,7 +26,14 @@ ...@@ -26,7 +26,14 @@
package java.nio.channels.spi; package java.nio.channels.spi;
import java.io.IOException; import java.io.IOException;
import java.nio.channels.*; import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.IllegalSelectorException;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
/** /**
...@@ -67,8 +74,8 @@ public abstract class AbstractSelectableChannel ...@@ -67,8 +74,8 @@ public abstract class AbstractSelectableChannel
// Lock for registration and configureBlocking operations // Lock for registration and configureBlocking operations
private final Object regLock = new Object(); private final Object regLock = new Object();
// Blocking mode, protected by regLock // True when non-blocking, need regLock to change;
boolean blocking = true; private volatile boolean nonBlocking;
/** /**
* Initializes a new instance of this class. * Initializes a new instance of this class.
...@@ -197,7 +204,7 @@ public abstract class AbstractSelectableChannel ...@@ -197,7 +204,7 @@ public abstract class AbstractSelectableChannel
throw new ClosedChannelException(); throw new ClosedChannelException();
if ((ops & ~validOps()) != 0) if ((ops & ~validOps()) != 0)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
if (blocking) if (isBlocking())
throw new IllegalBlockingModeException(); throw new IllegalBlockingModeException();
SelectionKey k = findKey(sel); SelectionKey k = findKey(sel);
if (k != null) { if (k != null) {
...@@ -264,9 +271,7 @@ public abstract class AbstractSelectableChannel ...@@ -264,9 +271,7 @@ public abstract class AbstractSelectableChannel
// -- Blocking -- // -- Blocking --
public final boolean isBlocking() { public final boolean isBlocking() {
synchronized (regLock) { return !nonBlocking;
return blocking;
}
} }
public final Object blockingLock() { public final Object blockingLock() {
...@@ -287,12 +292,13 @@ public abstract class AbstractSelectableChannel ...@@ -287,12 +292,13 @@ public abstract class AbstractSelectableChannel
synchronized (regLock) { synchronized (regLock) {
if (!isOpen()) if (!isOpen())
throw new ClosedChannelException(); throw new ClosedChannelException();
if (blocking == block) boolean blocking = !nonBlocking;
return this; if (block != blocking) {
if (block && haveValidKeys()) if (block && haveValidKeys())
throw new IllegalBlockingModeException(); throw new IllegalBlockingModeException();
implConfigureBlocking(block); implConfigureBlocking(block);
blocking = block; nonBlocking = !block;
}
} }
return this; return this;
} }
......
...@@ -49,9 +49,6 @@ class DatagramChannelImpl ...@@ -49,9 +49,6 @@ class DatagramChannelImpl
// Our file descriptor // Our file descriptor
private final FileDescriptor fd; private final FileDescriptor fd;
// fd value needed for dev/poll. This value will remain valid
// even after the value in the file descriptor object has been set to -1
private final int fdVal; private final int fdVal;
// The protocol family of the socket // The protocol family of the socket
...@@ -103,7 +100,6 @@ class DatagramChannelImpl ...@@ -103,7 +100,6 @@ class DatagramChannelImpl
// -- End of fields protected by stateLock // -- End of fields protected by stateLock
public DatagramChannelImpl(SelectorProvider sp) public DatagramChannelImpl(SelectorProvider sp)
throws IOException throws IOException
{ {
...@@ -138,16 +134,27 @@ class DatagramChannelImpl ...@@ -138,16 +134,27 @@ class DatagramChannelImpl
throw new UnsupportedOperationException("IPv6 not available"); throw new UnsupportedOperationException("IPv6 not available");
} }
} }
ResourceManager.beforeUdpCreate();
try {
this.family = family; this.family = family;
this.fd = Net.socket(family, false); this.fd = Net.socket(family, false);
this.fdVal = IOUtil.fdVal(fd); this.fdVal = IOUtil.fdVal(fd);
this.state = ST_UNCONNECTED; this.state = ST_UNCONNECTED;
} catch (IOException ioe) {
ResourceManager.afterUdpClose();
throw ioe;
}
} }
public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd) public DatagramChannelImpl(SelectorProvider sp, FileDescriptor fd)
throws IOException throws IOException
{ {
super(sp); super(sp);
// increment UDP count to match decrement when closing
ResourceManager.beforeUdpCreate();
this.family = Net.isIPv6Available() ? this.family = Net.isIPv6Available() ?
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
this.fd = fd; this.fd = fd;
...@@ -742,10 +749,9 @@ class DatagramChannelImpl ...@@ -742,10 +749,9 @@ class DatagramChannelImpl
localAddress = Net.localAddress(fd); localAddress = Net.localAddress(fd);
// flush any packets already received. // flush any packets already received.
boolean blocking = false;
synchronized (blockingLock()) { synchronized (blockingLock()) {
boolean blocking = isBlocking();
try { try {
blocking = isBlocking();
// remainder of each packet thrown away // remainder of each packet thrown away
ByteBuffer tmpBuf = ByteBuffer.allocate(1); ByteBuffer tmpBuf = ByteBuffer.allocate(1);
if (blocking) { if (blocking) {
......
/* /*
* Copyright (c) 2001, 2012, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,10 +25,22 @@ ...@@ -25,10 +25,22 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.*; import java.io.IOException;
import java.net.*; import java.net.DatagramPacket;
import java.nio.*; import java.net.DatagramSocket;
import java.nio.channels.*; import java.net.DatagramSocketImpl;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketOption;
import java.net.SocketTimeoutException;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.DatagramChannel;
import java.nio.channels.IllegalBlockingModeException;
// Make a datagram-socket channel look like a datagram socket. // Make a datagram-socket channel look like a datagram socket.
...@@ -178,7 +190,6 @@ public class DatagramSocketAdaptor ...@@ -178,7 +190,6 @@ public class DatagramSocketAdaptor
dc.configureBlocking(false); dc.configureBlocking(false);
try { try {
int n;
SocketAddress sender; SocketAddress sender;
if ((sender = dc.receive(bb)) != null) if ((sender = dc.receive(bb)) != null)
return sender; return sender;
...@@ -188,19 +199,18 @@ public class DatagramSocketAdaptor ...@@ -188,19 +199,18 @@ public class DatagramSocketAdaptor
throw new ClosedChannelException(); throw new ClosedChannelException();
long st = System.currentTimeMillis(); long st = System.currentTimeMillis();
int result = dc.poll(Net.POLLIN, to); int result = dc.poll(Net.POLLIN, to);
if (result > 0 && if (result > 0 && ((result & Net.POLLIN) != 0)) {
((result & Net.POLLIN) != 0)) {
if ((sender = dc.receive(bb)) != null) if ((sender = dc.receive(bb)) != null)
return sender; return sender;
} }
to -= System.currentTimeMillis() - st; to -= System.currentTimeMillis() - st;
if (to <= 0) if (to <= 0)
throw new SocketTimeoutException(); throw new SocketTimeoutException();
} }
} finally { } finally {
if (dc.isOpen()) try {
dc.configureBlocking(true); dc.configureBlocking(true);
} catch (ClosedChannelException e) { }
} }
} }
......
/* /*
* Copyright (c) 2000, 2013, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,9 +25,20 @@ ...@@ -25,9 +25,20 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.*; import java.io.IOException;
import java.net.*; import java.net.InetAddress;
import java.nio.channels.*; import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.StandardSocketOptions;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.NotYetBoundException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
// Make a server-socket channel look like a server socket. // Make a server-socket channel look like a server socket.
...@@ -37,7 +48,7 @@ import java.nio.channels.*; ...@@ -37,7 +48,7 @@ import java.nio.channels.*;
// class. // class.
// //
public class ServerSocketAdaptor // package-private class ServerSocketAdaptor // package-private
extends ServerSocket extends ServerSocket
{ {
...@@ -97,12 +108,16 @@ public class ServerSocketAdaptor // package-private ...@@ -97,12 +108,16 @@ public class ServerSocketAdaptor // package-private
throw new IllegalBlockingModeException(); throw new IllegalBlockingModeException();
try { try {
if (timeout == 0) { if (timeout == 0) {
// for compatibility reasons: accept connection if available
// when configured non-blocking
SocketChannel sc = ssc.accept(); SocketChannel sc = ssc.accept();
if (sc == null && !ssc.isBlocking()) if (sc == null && !ssc.isBlocking())
throw new IllegalBlockingModeException(); throw new IllegalBlockingModeException();
return sc.socket(); return sc.socket();
} }
if (!ssc.isBlocking())
throw new IllegalBlockingModeException();
ssc.configureBlocking(false); ssc.configureBlocking(false);
try { try {
SocketChannel sc; SocketChannel sc;
...@@ -121,10 +136,10 @@ public class ServerSocketAdaptor // package-private ...@@ -121,10 +136,10 @@ public class ServerSocketAdaptor // package-private
throw new SocketTimeoutException(); throw new SocketTimeoutException();
} }
} finally { } finally {
if (ssc.isOpen()) try {
ssc.configureBlocking(true); ssc.configureBlocking(true);
} catch (ClosedChannelException e) { }
} }
} catch (Exception x) { } catch (Exception x) {
Net.translateException(x); Net.translateException(x);
assert false; assert false;
...@@ -178,7 +193,6 @@ public class ServerSocketAdaptor // package-private ...@@ -178,7 +193,6 @@ public class ServerSocketAdaptor // package-private
if (!isBound()) if (!isBound())
return "ServerSocket[unbound]"; return "ServerSocket[unbound]";
return "ServerSocket[addr=" + getInetAddress() + return "ServerSocket[addr=" + getInetAddress() +
// ",port=" + getPort() +
",localport=" + getLocalPort() + "]"; ",localport=" + getLocalPort() + "]";
} }
......
...@@ -48,10 +48,7 @@ class ServerSocketChannelImpl ...@@ -48,10 +48,7 @@ class ServerSocketChannelImpl
// Our file descriptor // Our file descriptor
private final FileDescriptor fd; private final FileDescriptor fd;
private final int fdVal;
// fd value needed for dev/poll. This value will remain valid
// even after the value in the file descriptor object has been set to -1
private int fdVal;
// ID of native thread currently blocked in this channel, for signalling // ID of native thread currently blocked in this channel, for signalling
private volatile long thread = 0; private volatile long thread = 0;
......
/* /*
* Copyright (c) 2000, 2015, 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,11 +25,23 @@ ...@@ -25,11 +25,23 @@
package sun.nio.ch; package sun.nio.ch;
import java.io.*; import java.io.IOException;
import java.lang.ref.*; import java.io.InputStream;
import java.net.*; import java.io.OutputStream;
import java.nio.*; import java.net.InetAddress;
import java.nio.channels.*; import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.SocketImpl;
import java.net.SocketOption;
import java.net.SocketTimeoutException;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.IllegalBlockingModeException;
import java.nio.channels.SocketChannel;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.*; import java.util.*;
...@@ -47,7 +59,7 @@ import java.util.*; ...@@ -47,7 +59,7 @@ import java.util.*;
// java.net.Socket so as to simplify tracking future changes to that class. // java.net.Socket so as to simplify tracking future changes to that class.
// //
public class SocketAdaptor class SocketAdaptor
extends Socket extends Socket
{ {
...@@ -91,7 +103,6 @@ public class SocketAdaptor ...@@ -91,7 +103,6 @@ public class SocketAdaptor
throw new IllegalBlockingModeException(); throw new IllegalBlockingModeException();
try { try {
if (timeout == 0) { if (timeout == 0) {
sc.connect(remote); sc.connect(remote);
return; return;
...@@ -119,8 +130,9 @@ public class SocketAdaptor ...@@ -119,8 +130,9 @@ public class SocketAdaptor
} }
} }
} finally { } finally {
if (sc.isOpen()) try {
sc.configureBlocking(true); sc.configureBlocking(true);
} catch (ClosedChannelException e) { }
} }
} catch (Exception x) { } catch (Exception x) {
...@@ -188,10 +200,11 @@ public class SocketAdaptor ...@@ -188,10 +200,11 @@ public class SocketAdaptor
synchronized (sc.blockingLock()) { synchronized (sc.blockingLock()) {
if (!sc.isBlocking()) if (!sc.isBlocking())
throw new IllegalBlockingModeException(); throw new IllegalBlockingModeException();
if (timeout == 0) if (timeout == 0)
return sc.read(bb); return sc.read(bb);
sc.configureBlocking(false);
sc.configureBlocking(false);
try { try {
int n; int n;
if ((n = sc.read(bb)) != 0) if ((n = sc.read(bb)) != 0)
...@@ -211,10 +224,10 @@ public class SocketAdaptor ...@@ -211,10 +224,10 @@ public class SocketAdaptor
throw new SocketTimeoutException(); throw new SocketTimeoutException();
} }
} finally { } finally {
if (sc.isOpen()) try {
sc.configureBlocking(true); sc.configureBlocking(true);
} catch (ClosedChannelException e) { }
} }
} }
} }
} }
......
...@@ -50,9 +50,6 @@ class SocketChannelImpl ...@@ -50,9 +50,6 @@ class SocketChannelImpl
// Our file descriptor object // Our file descriptor object
private final FileDescriptor fd; private final FileDescriptor fd;
// fd value needed for dev/poll. This value will remain valid
// even after the value in the file descriptor object has been set to -1
private final int fdVal; private final int fdVal;
// IDs of native threads doing reads and writes, for signalling // IDs of native threads doing reads and writes, for signalling
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册