< prev index next >

src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java

Print this page




  31 import java.net.ServerSocket;
  32 import java.net.SocketAddress;
  33 import java.net.SocketOption;
  34 import java.net.SocketTimeoutException;
  35 import java.net.StandardSocketOptions;
  36 import java.nio.channels.AlreadyBoundException;
  37 import java.nio.channels.AsynchronousCloseException;
  38 import java.nio.channels.ClosedChannelException;
  39 import java.nio.channels.IllegalBlockingModeException;
  40 import java.nio.channels.NotYetBoundException;
  41 import java.nio.channels.SelectionKey;
  42 import java.nio.channels.ServerSocketChannel;
  43 import java.nio.channels.SocketChannel;
  44 import java.nio.channels.spi.SelectorProvider;
  45 import java.util.Collections;
  46 import java.util.HashSet;
  47 import java.util.Objects;
  48 import java.util.Set;
  49 import java.util.concurrent.locks.ReentrantLock;
  50 

  51 import sun.net.NetHooks;
  52 import sun.net.ext.ExtendedSocketOptions;
  53 
  54 /**
  55  * An implementation of ServerSocketChannels
  56  */
  57 
  58 class ServerSocketChannelImpl
  59     extends ServerSocketChannel
  60     implements SelChImpl
  61 {
  62     // Used to make native close and configure calls
  63     private static final NativeDispatcher nd = new SocketDispatcher();
  64 
  65     // Our file descriptor
  66     private final FileDescriptor fd;
  67     private final int fdVal;
  68 
  69     // Lock held by thread currently blocked on this channel
  70     private final ReentrantLock acceptLock = new ReentrantLock();


  76     // -- The following fields are protected by stateLock
  77 
  78     // Channel state, increases monotonically
  79     private static final int ST_INUSE = 0;
  80     private static final int ST_CLOSING = 1;
  81     private static final int ST_CLOSED = 2;
  82     private int state;
  83 
  84     // ID of native thread currently blocked in this channel, for signalling
  85     private long thread;
  86 
  87     // Binding
  88     private InetSocketAddress localAddress; // null => unbound
  89 
  90     // set true when exclusive binding is on and SO_REUSEADDR is emulated
  91     private boolean isReuseAddress;
  92 
  93     // Our socket adaptor, if any
  94     private ServerSocket socket;
  95 



  96     // -- End of fields protected by stateLock
  97 
  98 
  99     ServerSocketChannelImpl(SelectorProvider sp) {
 100         super(sp);
 101         this.fd = Net.serverSocket(true);
 102         this.fdVal = IOUtil.fdVal(fd);
 103     }
 104 
 105     ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
 106         throws IOException
 107     {
 108         super(sp);
 109         this.fd =  fd;
 110         this.fdVal = IOUtil.fdVal(fd);
 111         if (bound) {
 112             synchronized (stateLock) {
 113                 localAddress = Net.localAddress(fd);
 114             }
 115         }


 256                 thread = 0;
 257                 if (state == ST_CLOSING) {
 258                     tryFinishClose();
 259                 }
 260             }
 261             end(completed);
 262         }
 263     }
 264 
 265     @Override
 266     public SocketChannel accept() throws IOException {
 267         int n = 0;
 268         FileDescriptor newfd = new FileDescriptor();
 269         InetSocketAddress[] isaa = new InetSocketAddress[1];
 270 
 271         acceptLock.lock();
 272         try {
 273             boolean blocking = isBlocking();
 274             try {
 275                 begin(blocking);

 276                 n = Net.accept(this.fd, newfd, isaa);
 277                 if (blocking) {
 278                     while (IOStatus.okayToRetry(n) && isOpen()) {
 279                         park(Net.POLLIN);
 280                         n = Net.accept(this.fd, newfd, isaa);
 281                     }
 282                 }
 283             } finally {
 284                 end(blocking, n > 0);
 285                 assert IOStatus.check(n);
 286             }
 287         } finally {
 288             acceptLock.unlock();
 289         }
 290 
 291         if (n > 0) {
 292             return finishAccept(newfd, isaa[0]);
 293         } else {
 294             return null;
 295         }


 365         }
 366     }
 367 
 368     @Override
 369     protected void implConfigureBlocking(boolean block) throws IOException {
 370         acceptLock.lock();
 371         try {
 372             lockedConfigureBlocking(block);
 373         } finally {
 374             acceptLock.unlock();
 375         }
 376     }
 377 
 378     /**
 379      * Adjust the blocking mode while holding acceptLock.
 380      */
 381     private void lockedConfigureBlocking(boolean block) throws IOException {
 382         assert acceptLock.isHeldByCurrentThread();
 383         synchronized (stateLock) {
 384             ensureOpen();
 385             IOUtil.configureBlocking(fd, block);


















 386         }
 387     }
 388 
 389     /**
 390      * Closes the socket if there are no accept in progress and the channel is
 391      * not registered with a Selector.
 392      */
 393     private boolean tryClose() throws IOException {
 394         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
 395         if ((thread == 0) && !isRegistered()) {
 396             state = ST_CLOSED;
 397             nd.close(fd);
 398             return true;
 399         } else {
 400             return false;
 401         }
 402     }
 403 
 404     /**
 405      * Invokes tryClose to attempt to close the socket.


 409     private void tryFinishClose() {
 410         try {
 411             tryClose();
 412         } catch (IOException ignore) { }
 413     }
 414 
 415     /**
 416      * Closes this channel when configured in blocking mode.
 417      *
 418      * If there is an accept in progress then the socket is pre-closed and the
 419      * accept thread is signalled, in which case the final close is deferred
 420      * until the accept aborts.
 421      */
 422     private void implCloseBlockingMode() throws IOException {
 423         synchronized (stateLock) {
 424             assert state < ST_CLOSING;
 425             state = ST_CLOSING;
 426             if (!tryClose()) {
 427                 long th = thread;
 428                 if (th != 0) {


 429                     nd.preClose(fd);
 430                     NativeThread.signal(th);

 431                 }
 432             }
 433         }
 434     }
 435 
 436     /**
 437      * Closes this channel when configured in non-blocking mode.
 438      *
 439      * If the channel is registered with a Selector then the close is deferred
 440      * until the channel is flushed from all Selectors.
 441      */
 442     private void implCloseNonBlockingMode() throws IOException {
 443         synchronized (stateLock) {
 444             assert state < ST_CLOSING;
 445             state = ST_CLOSING;
 446         }
 447         // wait for any accept to complete before trying to close
 448         acceptLock.lock();
 449         acceptLock.unlock();
 450         synchronized (stateLock) {




  31 import java.net.ServerSocket;
  32 import java.net.SocketAddress;
  33 import java.net.SocketOption;
  34 import java.net.SocketTimeoutException;
  35 import java.net.StandardSocketOptions;
  36 import java.nio.channels.AlreadyBoundException;
  37 import java.nio.channels.AsynchronousCloseException;
  38 import java.nio.channels.ClosedChannelException;
  39 import java.nio.channels.IllegalBlockingModeException;
  40 import java.nio.channels.NotYetBoundException;
  41 import java.nio.channels.SelectionKey;
  42 import java.nio.channels.ServerSocketChannel;
  43 import java.nio.channels.SocketChannel;
  44 import java.nio.channels.spi.SelectorProvider;
  45 import java.util.Collections;
  46 import java.util.HashSet;
  47 import java.util.Objects;
  48 import java.util.Set;
  49 import java.util.concurrent.locks.ReentrantLock;
  50 
  51 import jdk.internal.misc.Strands;
  52 import sun.net.NetHooks;
  53 import sun.net.ext.ExtendedSocketOptions;
  54 
  55 /**
  56  * An implementation of ServerSocketChannels
  57  */
  58 
  59 class ServerSocketChannelImpl
  60     extends ServerSocketChannel
  61     implements SelChImpl
  62 {
  63     // Used to make native close and configure calls
  64     private static final NativeDispatcher nd = new SocketDispatcher();
  65 
  66     // Our file descriptor
  67     private final FileDescriptor fd;
  68     private final int fdVal;
  69 
  70     // Lock held by thread currently blocked on this channel
  71     private final ReentrantLock acceptLock = new ReentrantLock();


  77     // -- The following fields are protected by stateLock
  78 
  79     // Channel state, increases monotonically
  80     private static final int ST_INUSE = 0;
  81     private static final int ST_CLOSING = 1;
  82     private static final int ST_CLOSED = 2;
  83     private int state;
  84 
  85     // ID of native thread currently blocked in this channel, for signalling
  86     private long thread;
  87 
  88     // Binding
  89     private InetSocketAddress localAddress; // null => unbound
  90 
  91     // set true when exclusive binding is on and SO_REUSEADDR is emulated
  92     private boolean isReuseAddress;
  93 
  94     // Our socket adaptor, if any
  95     private ServerSocket socket;
  96 
  97     // lazily set to true when the socket is configured non-blocking
  98     private volatile boolean nonBlocking;
  99 
 100     // -- End of fields protected by stateLock
 101 
 102 
 103     ServerSocketChannelImpl(SelectorProvider sp) {
 104         super(sp);
 105         this.fd = Net.serverSocket(true);
 106         this.fdVal = IOUtil.fdVal(fd);
 107     }
 108 
 109     ServerSocketChannelImpl(SelectorProvider sp, FileDescriptor fd, boolean bound)
 110         throws IOException
 111     {
 112         super(sp);
 113         this.fd =  fd;
 114         this.fdVal = IOUtil.fdVal(fd);
 115         if (bound) {
 116             synchronized (stateLock) {
 117                 localAddress = Net.localAddress(fd);
 118             }
 119         }


 260                 thread = 0;
 261                 if (state == ST_CLOSING) {
 262                     tryFinishClose();
 263                 }
 264             }
 265             end(completed);
 266         }
 267     }
 268 
 269     @Override
 270     public SocketChannel accept() throws IOException {
 271         int n = 0;
 272         FileDescriptor newfd = new FileDescriptor();
 273         InetSocketAddress[] isaa = new InetSocketAddress[1];
 274 
 275         acceptLock.lock();
 276         try {
 277             boolean blocking = isBlocking();
 278             try {
 279                 begin(blocking);
 280                 lockedConfigureNonBlockingIfFiber();
 281                 n = Net.accept(this.fd, newfd, isaa);
 282                 if (blocking) {
 283                     while (IOStatus.okayToRetry(n) && isOpen()) {
 284                         park(Net.POLLIN);
 285                         n = Net.accept(this.fd, newfd, isaa);
 286                     }
 287                 }
 288             } finally {
 289                 end(blocking, n > 0);
 290                 assert IOStatus.check(n);
 291             }
 292         } finally {
 293             acceptLock.unlock();
 294         }
 295 
 296         if (n > 0) {
 297             return finishAccept(newfd, isaa[0]);
 298         } else {
 299             return null;
 300         }


 370         }
 371     }
 372 
 373     @Override
 374     protected void implConfigureBlocking(boolean block) throws IOException {
 375         acceptLock.lock();
 376         try {
 377             lockedConfigureBlocking(block);
 378         } finally {
 379             acceptLock.unlock();
 380         }
 381     }
 382 
 383     /**
 384      * Adjust the blocking mode while holding acceptLock.
 385      */
 386     private void lockedConfigureBlocking(boolean block) throws IOException {
 387         assert acceptLock.isHeldByCurrentThread();
 388         synchronized (stateLock) {
 389             ensureOpen();
 390             // do nothing if fiber has forced the socket to be non-blocking
 391             if (!nonBlocking) {
 392                 IOUtil.configureBlocking(fd, block);
 393             }
 394         }
 395     }
 396 
 397     /**
 398      * Ensures that the socket is configured non-blocking when the current
 399      * strand is a fiber.
 400      */
 401     private void lockedConfigureNonBlockingIfFiber() throws IOException {
 402         assert acceptLock.isHeldByCurrentThread();
 403         if (!nonBlocking && (Strands.currentStrand() instanceof Fiber)) {
 404             synchronized (stateLock) {
 405                 ensureOpen();
 406                 IOUtil.configureBlocking(fd, false);
 407                 nonBlocking = true;
 408             }
 409         }
 410     }
 411 
 412     /**
 413      * Closes the socket if there are no accept in progress and the channel is
 414      * not registered with a Selector.
 415      */
 416     private boolean tryClose() throws IOException {
 417         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
 418         if ((thread == 0) && !isRegistered()) {
 419             state = ST_CLOSED;
 420             nd.close(fd);
 421             return true;
 422         } else {
 423             return false;
 424         }
 425     }
 426 
 427     /**
 428      * Invokes tryClose to attempt to close the socket.


 432     private void tryFinishClose() {
 433         try {
 434             tryClose();
 435         } catch (IOException ignore) { }
 436     }
 437 
 438     /**
 439      * Closes this channel when configured in blocking mode.
 440      *
 441      * If there is an accept in progress then the socket is pre-closed and the
 442      * accept thread is signalled, in which case the final close is deferred
 443      * until the accept aborts.
 444      */
 445     private void implCloseBlockingMode() throws IOException {
 446         synchronized (stateLock) {
 447             assert state < ST_CLOSING;
 448             state = ST_CLOSING;
 449             if (!tryClose()) {
 450                 long th = thread;
 451                 if (th != 0) {
 452                     if (NativeThread.isFiber(th))
 453                         Poller.stopPoll(fdVal);
 454                     nd.preClose(fd);
 455                     if (NativeThread.isKernelThread(th))
 456                         NativeThread.signal(th);
 457                 }
 458             }
 459         }
 460     }
 461 
 462     /**
 463      * Closes this channel when configured in non-blocking mode.
 464      *
 465      * If the channel is registered with a Selector then the close is deferred
 466      * until the channel is flushed from all Selectors.
 467      */
 468     private void implCloseNonBlockingMode() throws IOException {
 469         synchronized (stateLock) {
 470             assert state < ST_CLOSING;
 471             state = ST_CLOSING;
 472         }
 473         // wait for any accept to complete before trying to close
 474         acceptLock.lock();
 475         acceptLock.unlock();
 476         synchronized (stateLock) {


< prev index next >