< prev index next >

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

Print this page

 86     // -- The following fields are protected by stateLock
 87 
 88     // Channel state, increases monotonically
 89     private static final int ST_INUSE = 0;
 90     private static final int ST_CLOSING = 1;
 91     private static final int ST_CLOSED = 2;
 92     private int state;
 93 
 94     // ID of native thread currently blocked in this channel, for signalling
 95     private long thread;
 96 
 97     // Binding
 98     private SocketAddress localAddress; // null => unbound
 99 
100     // set true when exclusive binding is on and SO_REUSEADDR is emulated
101     private boolean isReuseAddress;
102 
103     // Our socket adaptor, if any
104     private ServerSocket socket;
105 



106     // -- End of fields protected by stateLock
107 
108     ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
109         this(sp, Net.isIPv6Available() ? INET6 : INET);
110     }
111 
112     ServerSocketChannelImpl(SelectorProvider sp, ProtocolFamily family)
113         throws IOException
114     {
115         super(sp);
116         Objects.requireNonNull(family, "'family' is null");
117         if ((family != INET) && (family != INET6) && (family != UNIX)) {
118             throw new UnsupportedOperationException("Protocol family not supported");
119         }
120         if (family == INET6 && !Net.isIPv6Available()) {
121             throw new UnsupportedOperationException("IPv6 not available");
122         }
123 
124         this.family = family;
125         if (family == UNIX) {

371                 thread = 0;
372                 if (state == ST_CLOSING) {
373                     tryFinishClose();
374                 }
375             }
376             end(completed);
377         }
378     }
379 
380     @Override
381     public SocketChannel accept() throws IOException {
382         int n = 0;
383         FileDescriptor newfd = new FileDescriptor();
384         SocketAddress[] saa = new SocketAddress[1];
385 
386         acceptLock.lock();
387         try {
388             boolean blocking = isBlocking();
389             try {
390                 begin(blocking);

391                 n = implAccept(this.fd, newfd, saa);
392                 if (blocking) {
393                     while (IOStatus.okayToRetry(n) && isOpen()) {
394                         park(Net.POLLIN);
395                         n = implAccept(this.fd, newfd, saa);
396                     }
397                 }
398             } finally {
399                 end(blocking, n > 0);
400                 assert IOStatus.check(n);
401             }
402         } finally {
403             acceptLock.unlock();
404         }
405 
406         if (n > 0) {
407             return finishAccept(newfd, saa[0]);
408         } else {
409             return null;
410         }

497                 }
498             }
499             return new SocketChannelImpl(provider(), family, newfd, sa);
500         } catch (Exception e) {
501             nd.close(newfd);
502             throw e;
503         }
504     }
505 
506     @Override
507     protected void implConfigureBlocking(boolean block) throws IOException {
508         acceptLock.lock();
509         try {
510             lockedConfigureBlocking(block);
511         } finally {
512             acceptLock.unlock();
513         }
514     }
515 
516     /**
517      * Adjust the blocking. acceptLock must already be held.
518      */
519     private void lockedConfigureBlocking(boolean block) throws IOException {
520         assert acceptLock.isHeldByCurrentThread();
521         synchronized (stateLock) {
522             ensureOpen();
523             IOUtil.configureBlocking(fd, block);



524         }
525     }
526 
527     /**
528      * Adjusts the blocking mode if the channel is open. acceptLock must already
529      * be held.
530      *
531      * @return {@code true} if the blocking mode was adjusted, {@code false} if
532      *         the blocking mode was not adjusted because the channel is closed
533      */
534     private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
535         assert acceptLock.isHeldByCurrentThread();
536         synchronized (stateLock) {
537             if (isOpen()) {

538                 IOUtil.configureBlocking(fd, block);
539                 return true;
540             } else {
541                 return false;
542             }
543         }
544     }
545 















546     /**
547      * Closes the socket if there are no accept in progress and the channel is
548      * not registered with a Selector.
549      */
550     private boolean tryClose() throws IOException {
551         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
552         if ((thread == 0) && !isRegistered()) {
553             state = ST_CLOSED;
554             nd.close(fd);
555             return true;
556         } else {
557             return false;
558         }
559     }
560 
561     /**
562      * Invokes tryClose to attempt to close the socket.
563      *
564      * This method is used for deferred closing by I/O and Selector operations.
565      */
566     private void tryFinishClose() {
567         try {
568             tryClose();
569         } catch (IOException ignore) { }
570     }
571 
572     /**
573      * Closes this channel when configured in blocking mode.
574      *
575      * If there is an accept in progress then the socket is pre-closed and the
576      * accept thread is signalled, in which case the final close is deferred
577      * until the accept aborts.
578      */
579     private void implCloseBlockingMode() throws IOException {
580         synchronized (stateLock) {
581             assert state < ST_CLOSING;
582             state = ST_CLOSING;
583             if (!tryClose()) {
584                 long th = thread;
585                 if (th != 0) {
586                     nd.preClose(fd);
587                     NativeThread.signal(th);




588                 }
589             }
590         }
591     }
592 
593     /**
594      * Closes this channel when configured in non-blocking mode.
595      *
596      * If the channel is registered with a Selector then the close is deferred
597      * until the channel is flushed from all Selectors.
598      */
599     private void implCloseNonBlockingMode() throws IOException {
600         synchronized (stateLock) {
601             assert state < ST_CLOSING;
602             state = ST_CLOSING;
603         }
604         // wait for any accept to complete before trying to close
605         acceptLock.lock();
606         acceptLock.unlock();
607         synchronized (stateLock) {

 86     // -- The following fields are protected by stateLock
 87 
 88     // Channel state, increases monotonically
 89     private static final int ST_INUSE = 0;
 90     private static final int ST_CLOSING = 1;
 91     private static final int ST_CLOSED = 2;
 92     private int state;
 93 
 94     // ID of native thread currently blocked in this channel, for signalling
 95     private long thread;
 96 
 97     // Binding
 98     private SocketAddress localAddress; // null => unbound
 99 
100     // set true when exclusive binding is on and SO_REUSEADDR is emulated
101     private boolean isReuseAddress;
102 
103     // Our socket adaptor, if any
104     private ServerSocket socket;
105 
106     // lazily set to true when the socket is configured non-blocking
107     private volatile boolean nonBlocking;
108 
109     // -- End of fields protected by stateLock
110 
111     ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
112         this(sp, Net.isIPv6Available() ? INET6 : INET);
113     }
114 
115     ServerSocketChannelImpl(SelectorProvider sp, ProtocolFamily family)
116         throws IOException
117     {
118         super(sp);
119         Objects.requireNonNull(family, "'family' is null");
120         if ((family != INET) && (family != INET6) && (family != UNIX)) {
121             throw new UnsupportedOperationException("Protocol family not supported");
122         }
123         if (family == INET6 && !Net.isIPv6Available()) {
124             throw new UnsupportedOperationException("IPv6 not available");
125         }
126 
127         this.family = family;
128         if (family == UNIX) {

374                 thread = 0;
375                 if (state == ST_CLOSING) {
376                     tryFinishClose();
377                 }
378             }
379             end(completed);
380         }
381     }
382 
383     @Override
384     public SocketChannel accept() throws IOException {
385         int n = 0;
386         FileDescriptor newfd = new FileDescriptor();
387         SocketAddress[] saa = new SocketAddress[1];
388 
389         acceptLock.lock();
390         try {
391             boolean blocking = isBlocking();
392             try {
393                 begin(blocking);
394                 lockedConfigureNonBlockingIfNeeded();
395                 n = implAccept(this.fd, newfd, saa);
396                 if (blocking) {
397                     while (IOStatus.okayToRetry(n) && isOpen()) {
398                         park(Net.POLLIN);
399                         n = implAccept(this.fd, newfd, saa);
400                     }
401                 }
402             } finally {
403                 end(blocking, n > 0);
404                 assert IOStatus.check(n);
405             }
406         } finally {
407             acceptLock.unlock();
408         }
409 
410         if (n > 0) {
411             return finishAccept(newfd, saa[0]);
412         } else {
413             return null;
414         }

501                 }
502             }
503             return new SocketChannelImpl(provider(), family, newfd, sa);
504         } catch (Exception e) {
505             nd.close(newfd);
506             throw e;
507         }
508     }
509 
510     @Override
511     protected void implConfigureBlocking(boolean block) throws IOException {
512         acceptLock.lock();
513         try {
514             lockedConfigureBlocking(block);
515         } finally {
516             acceptLock.unlock();
517         }
518     }
519 
520     /**
521      * Adjusts the blocking mode.
522      */
523     private void lockedConfigureBlocking(boolean block) throws IOException {
524         assert acceptLock.isHeldByCurrentThread();
525         synchronized (stateLock) {
526             ensureOpen();
527             // do nothing if virtual thread has forced the socket to be non-blocking
528             if (!nonBlocking) {
529                 IOUtil.configureBlocking(fd, block);
530             }
531         }
532     }
533 
534     /**
535      * Attempts to adjusts the blocking mode if the channel is open.
536      * @return {@code true} if the blocking mode was adjusted



537      */
538     private boolean tryLockedConfigureBlocking(boolean block) throws IOException {
539         assert acceptLock.isHeldByCurrentThread();
540         synchronized (stateLock) {
541             // do nothing if virtual thread has forced the socket to be non-blocking
542             if (!nonBlocking && isOpen()) {
543                 IOUtil.configureBlocking(fd, block);
544                 return true;
545             } else {
546                 return false;
547             }
548         }
549     }
550 
551     /**
552      * Ensures that the socket is configured non-blocking when on a virtual
553      * thread.
554      */
555     private void lockedConfigureNonBlockingIfNeeded() throws IOException {
556         assert acceptLock.isHeldByCurrentThread();
557         if (!nonBlocking && (Thread.currentThread().isVirtual())) {
558             synchronized (stateLock) {
559                 ensureOpen();
560                 IOUtil.configureBlocking(fd, false);
561                 nonBlocking = true;
562             }
563         }
564     }
565 
566     /**
567      * Closes the socket if there are no accept in progress and the channel is
568      * not registered with a Selector.
569      */
570     private boolean tryClose() throws IOException {
571         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
572         if ((thread == 0) && !isRegistered()) {
573             state = ST_CLOSED;
574             nd.close(fd);
575             return true;
576         } else {
577             return false;
578         }
579     }
580 
581     /**
582      * Invokes tryClose to attempt to close the socket.
583      *
584      * This method is used for deferred closing by I/O and Selector operations.
585      */
586     private void tryFinishClose() {
587         try {
588             tryClose();
589         } catch (IOException ignore) { }
590     }
591 
592     /**
593      * Closes this channel when configured in blocking mode.
594      *
595      * If there is an accept in progress then the socket is pre-closed and the
596      * accept thread is signalled, in which case the final close is deferred
597      * until the accept aborts.
598      */
599     private void implCloseBlockingMode() throws IOException {
600         synchronized (stateLock) {
601             assert state < ST_CLOSING;
602             state = ST_CLOSING;
603             if (!tryClose()) {
604                 long th = thread;
605                 if (th != 0) {
606                     if (NativeThread.isVirtualThread(th)) {
607                         Poller.stopPoll(fdVal);
608                     } else {
609                         nd.preClose(fd);
610                         NativeThread.signal(th);
611                     }
612                 }
613             }
614         }
615     }
616 
617     /**
618      * Closes this channel when configured in non-blocking mode.
619      *
620      * If the channel is registered with a Selector then the close is deferred
621      * until the channel is flushed from all Selectors.
622      */
623     private void implCloseNonBlockingMode() throws IOException {
624         synchronized (stateLock) {
625             assert state < ST_CLOSING;
626             state = ST_CLOSING;
627         }
628         // wait for any accept to complete before trying to close
629         acceptLock.lock();
630         acceptLock.unlock();
631         synchronized (stateLock) {
< prev index next >