73
74 // Our file descriptor
75 private final FileDescriptor fd;
76 private final int fdVal;
77
78 // Lock held by thread currently blocked on this channel
79 private final ReentrantLock acceptLock = new ReentrantLock();
80
81 // Lock held by any thread that modifies the state fields declared below
82 // DO NOT invoke a blocking I/O operation while holding this lock!
83 private final Object stateLock = new Object();
84
85 // -- The following fields are protected by stateLock
86
87 // Channel state, increases monotonically
88 private static final int ST_INUSE = 0;
89 private static final int ST_CLOSING = 1;
90 private static final int ST_CLOSED = 2;
91 private int state;
92
93 // ID of native thread currently blocked in this channel, for signalling
94 private long thread;
95
96 // Binding
97 private SocketAddress localAddress; // null => unbound
98
99 // set true when exclusive binding is on and SO_REUSEADDR is emulated
100 private boolean isReuseAddress;
101
102 // Our socket adaptor, if any
103 private ServerSocket socket;
104
105 // True if the channel's socket has been forced into non-blocking mode
106 // by a virtual thread. It cannot be reset. When the channel is in
107 // blocking mode and the channel's socket is in non-blocking mode then
108 // operations that don't complete immediately will poll the socket and
109 // preserve the semantics of blocking operations.
110 private volatile boolean forcedNonBlocking;
111
112 // -- End of fields protected by stateLock
113
114 ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
332 }
333 Net.bind(family, fd, isa.getAddress(), isa.getPort());
334 Net.listen(fd, backlog < 1 ? 50 : backlog);
335 return Net.localAddress(fd);
336 }
337
338 /**
339 * Marks the beginning of an I/O operation that might block.
340 *
341 * @throws ClosedChannelException if the channel is closed
342 * @throws NotYetBoundException if the channel's socket has not been bound yet
343 */
344 private void begin(boolean blocking) throws ClosedChannelException {
345 if (blocking)
346 begin(); // set blocker to close channel if interrupted
347 synchronized (stateLock) {
348 ensureOpen();
349 if (localAddress == null)
350 throw new NotYetBoundException();
351 if (blocking)
352 thread = NativeThread.current();
353 }
354 }
355
356 /**
357 * Marks the end of an I/O operation that may have blocked.
358 *
359 * @throws AsynchronousCloseException if the channel was closed due to this
360 * thread being interrupted on a blocking I/O operation.
361 */
362 private void end(boolean blocking, boolean completed)
363 throws AsynchronousCloseException
364 {
365 if (blocking) {
366 synchronized (stateLock) {
367 thread = 0;
368 if (state == ST_CLOSING) {
369 tryFinishClose();
370 }
371 }
372 end(completed);
373 }
374 }
375
376 @Override
377 public SocketChannel accept() throws IOException {
378 int n = 0;
379 FileDescriptor newfd = new FileDescriptor();
380 SocketAddress[] saa = new SocketAddress[1];
381
382 acceptLock.lock();
383 try {
384 ensureOpen();
385 boolean blocking = isBlocking();
386 try {
387 begin(blocking);
534 /**
535 * Ensures that the socket is configured non-blocking when on a virtual thread.
536 */
537 private void configureSocketNonBlockingIfVirtualThread() throws IOException {
538 assert acceptLock.isHeldByCurrentThread();
539 if (!forcedNonBlocking && Thread.currentThread().isVirtual()) {
540 synchronized (stateLock) {
541 ensureOpen();
542 IOUtil.configureBlocking(fd, false);
543 forcedNonBlocking = true;
544 }
545 }
546 }
547
548 /**
549 * Closes the socket if there are no accept in progress and the channel is
550 * not registered with a Selector.
551 */
552 private boolean tryClose() throws IOException {
553 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
554 if ((thread == 0) && !isRegistered()) {
555 state = ST_CLOSED;
556 nd.close(fd);
557 return true;
558 } else {
559 return false;
560 }
561 }
562
563 /**
564 * Invokes tryClose to attempt to close the socket.
565 *
566 * This method is used for deferred closing by I/O and Selector operations.
567 */
568 private void tryFinishClose() {
569 try {
570 tryClose();
571 } catch (IOException ignore) { }
572 }
573
574 /**
575 * Closes this channel when configured in blocking mode.
576 *
577 * If there is an accept in progress then the socket is pre-closed and the
578 * accept thread is signalled, in which case the final close is deferred
579 * until the accept aborts.
580 */
581 private void implCloseBlockingMode() throws IOException {
582 synchronized (stateLock) {
583 assert state < ST_CLOSING;
584 state = ST_CLOSING;
585 if (!tryClose()) {
586 nd.preClose(fd, thread, 0);
587 }
588 }
589 }
590
591 /**
592 * Closes this channel when configured in non-blocking mode.
593 *
594 * If the channel is registered with a Selector then the close is deferred
595 * until the channel is flushed from all Selectors.
596 */
597 private void implCloseNonBlockingMode() throws IOException {
598 synchronized (stateLock) {
599 assert state < ST_CLOSING;
600 state = ST_CLOSING;
601 }
602 // wait for any accept to complete before trying to close
603 acceptLock.lock();
604 acceptLock.unlock();
605 synchronized (stateLock) {
606 if (state == ST_CLOSING) {
|
73
74 // Our file descriptor
75 private final FileDescriptor fd;
76 private final int fdVal;
77
78 // Lock held by thread currently blocked on this channel
79 private final ReentrantLock acceptLock = new ReentrantLock();
80
81 // Lock held by any thread that modifies the state fields declared below
82 // DO NOT invoke a blocking I/O operation while holding this lock!
83 private final Object stateLock = new Object();
84
85 // -- The following fields are protected by stateLock
86
87 // Channel state, increases monotonically
88 private static final int ST_INUSE = 0;
89 private static final int ST_CLOSING = 1;
90 private static final int ST_CLOSED = 2;
91 private int state;
92
93 // Thread currently blocked in this channel, for signalling
94 private Thread thread;
95
96 // Binding
97 private SocketAddress localAddress; // null => unbound
98
99 // set true when exclusive binding is on and SO_REUSEADDR is emulated
100 private boolean isReuseAddress;
101
102 // Our socket adaptor, if any
103 private ServerSocket socket;
104
105 // True if the channel's socket has been forced into non-blocking mode
106 // by a virtual thread. It cannot be reset. When the channel is in
107 // blocking mode and the channel's socket is in non-blocking mode then
108 // operations that don't complete immediately will poll the socket and
109 // preserve the semantics of blocking operations.
110 private volatile boolean forcedNonBlocking;
111
112 // -- End of fields protected by stateLock
113
114 ServerSocketChannelImpl(SelectorProvider sp) throws IOException {
332 }
333 Net.bind(family, fd, isa.getAddress(), isa.getPort());
334 Net.listen(fd, backlog < 1 ? 50 : backlog);
335 return Net.localAddress(fd);
336 }
337
338 /**
339 * Marks the beginning of an I/O operation that might block.
340 *
341 * @throws ClosedChannelException if the channel is closed
342 * @throws NotYetBoundException if the channel's socket has not been bound yet
343 */
344 private void begin(boolean blocking) throws ClosedChannelException {
345 if (blocking)
346 begin(); // set blocker to close channel if interrupted
347 synchronized (stateLock) {
348 ensureOpen();
349 if (localAddress == null)
350 throw new NotYetBoundException();
351 if (blocking)
352 thread = NativeThread.threadToSignal();
353 }
354 }
355
356 /**
357 * Marks the end of an I/O operation that may have blocked.
358 *
359 * @throws AsynchronousCloseException if the channel was closed due to this
360 * thread being interrupted on a blocking I/O operation.
361 */
362 private void end(boolean blocking, boolean completed)
363 throws AsynchronousCloseException
364 {
365 if (blocking) {
366 synchronized (stateLock) {
367 thread = null;
368 if (state == ST_CLOSING) {
369 tryFinishClose();
370 }
371 }
372 end(completed);
373 }
374 }
375
376 @Override
377 public SocketChannel accept() throws IOException {
378 int n = 0;
379 FileDescriptor newfd = new FileDescriptor();
380 SocketAddress[] saa = new SocketAddress[1];
381
382 acceptLock.lock();
383 try {
384 ensureOpen();
385 boolean blocking = isBlocking();
386 try {
387 begin(blocking);
534 /**
535 * Ensures that the socket is configured non-blocking when on a virtual thread.
536 */
537 private void configureSocketNonBlockingIfVirtualThread() throws IOException {
538 assert acceptLock.isHeldByCurrentThread();
539 if (!forcedNonBlocking && Thread.currentThread().isVirtual()) {
540 synchronized (stateLock) {
541 ensureOpen();
542 IOUtil.configureBlocking(fd, false);
543 forcedNonBlocking = true;
544 }
545 }
546 }
547
548 /**
549 * Closes the socket if there are no accept in progress and the channel is
550 * not registered with a Selector.
551 */
552 private boolean tryClose() throws IOException {
553 assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
554 if ((thread == null) && !isRegistered()) {
555 state = ST_CLOSED;
556 nd.close(fd);
557 return true;
558 } else {
559 return false;
560 }
561 }
562
563 /**
564 * Invokes tryClose to attempt to close the socket.
565 *
566 * This method is used for deferred closing by I/O and Selector operations.
567 */
568 private void tryFinishClose() {
569 try {
570 tryClose();
571 } catch (IOException ignore) { }
572 }
573
574 /**
575 * Closes this channel when configured in blocking mode.
576 *
577 * If there is an accept in progress then the socket is pre-closed and the
578 * accept thread is signalled, in which case the final close is deferred
579 * until the accept aborts.
580 */
581 private void implCloseBlockingMode() throws IOException {
582 synchronized (stateLock) {
583 assert state < ST_CLOSING;
584 state = ST_CLOSING;
585 if (!tryClose()) {
586 nd.preClose(fd, thread, null);
587 }
588 }
589 }
590
591 /**
592 * Closes this channel when configured in non-blocking mode.
593 *
594 * If the channel is registered with a Selector then the close is deferred
595 * until the channel is flushed from all Selectors.
596 */
597 private void implCloseNonBlockingMode() throws IOException {
598 synchronized (stateLock) {
599 assert state < ST_CLOSING;
600 state = ST_CLOSING;
601 }
602 // wait for any accept to complete before trying to close
603 acceptLock.lock();
604 acceptLock.unlock();
605 synchronized (stateLock) {
606 if (state == ST_CLOSING) {
|