< prev index next >

src/java.base/unix/classes/sun/nio/ch/SourceChannelImpl.java

Print this page

 47     // The file descriptor associated with this channel
 48     private final FileDescriptor fd;
 49     private final int fdVal;
 50 
 51     // Lock held by current reading thread
 52     private final ReentrantLock readLock = new ReentrantLock();
 53 
 54     // Lock held by any thread that modifies the state fields declared below
 55     // DO NOT invoke a blocking I/O operation while holding this lock!
 56     private final Object stateLock = new Object();
 57 
 58     // -- The following fields are protected by stateLock
 59 
 60     // Channel state
 61     private static final int ST_INUSE = 0;
 62     private static final int ST_CLOSING = 1;
 63     private static final int ST_CLOSED = 2;
 64     private int state;
 65 
 66     // ID of native thread doing read, for signalling
 67     private long thread;
 68 
 69     // True if the channel's socket has been forced into non-blocking mode
 70     // by a virtual thread. It cannot be reset. When the channel is in
 71     // blocking mode and the channel's socket is in non-blocking mode then
 72     // operations that don't complete immediately will poll the socket and
 73     // preserve the semantics of blocking operations.
 74     private volatile boolean forcedNonBlocking;
 75 
 76     // -- End of fields protected by stateLock
 77 
 78 
 79     public FileDescriptor getFD() {
 80         return fd;
 81     }
 82 
 83     public int getFDVal() {
 84         return fdVal;
 85     }
 86 
 87     SourceChannelImpl(SelectorProvider sp, FileDescriptor fd) throws IOException {

103     /**
104      * Ensures that the socket is configured non-blocking when on a virtual thread.
105      */
106     private void configureSocketNonBlockingIfVirtualThread() throws IOException {
107         assert readLock.isHeldByCurrentThread();
108         if (!forcedNonBlocking && Thread.currentThread().isVirtual()) {
109             synchronized (stateLock) {
110                 ensureOpen();
111                 IOUtil.configureBlocking(fd, false);
112                 forcedNonBlocking = true;
113             }
114         }
115     }
116 
117     /**
118      * Closes the read end of the pipe if there are no read operation in
119      * progress and the channel is not registered with a Selector.
120      */
121     private boolean tryClose() throws IOException {
122         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
123         if (thread == 0 && !isRegistered()) {
124             state = ST_CLOSED;
125             nd.close(fd);
126             return true;
127         } else {
128             return false;
129         }
130     }
131 
132     /**
133      * Invokes tryClose to attempt to close the read end of the pipe.
134      *
135      * This method is used for deferred closing by I/O and Selector operations.
136      */
137     private void tryFinishClose() {
138         try {
139             tryClose();
140         } catch (IOException ignore) { }
141     }
142 
143     /**
144      * Closes this channel when configured in blocking mode.
145      *
146      * If there is a read operation in progress then the read-end of the pipe
147      * is pre-closed and the reader is signalled, in which case the final close
148      * is deferred until the reader aborts.
149      */
150     private void implCloseBlockingMode() throws IOException {
151         synchronized (stateLock) {
152             assert state < ST_CLOSING;
153             state = ST_CLOSING;
154             if (!tryClose()) {
155                 nd.preClose(fd, thread, 0);
156             }
157         }
158     }
159 
160     /**
161      * Closes this channel when configured in non-blocking mode.
162      *
163      * If the channel is registered with a Selector then the close is deferred
164      * until the channel is flushed from all Selectors.
165      */
166     private void implCloseNonBlockingMode() throws IOException {
167         synchronized (stateLock) {
168             assert state < ST_CLOSING;
169             state = ST_CLOSING;
170         }
171         // wait for any read operation to complete before trying to close
172         readLock.lock();
173         readLock.unlock();
174         synchronized (stateLock) {
175             if (state == ST_CLOSING) {

252     public int translateInterestOps(int ops) {
253         int newOps = 0;
254         if (ops == SelectionKey.OP_READ)
255             newOps |= Net.POLLIN;
256         return newOps;
257     }
258 
259     /**
260      * Marks the beginning of a read operation that might block.
261      *
262      * @throws ClosedChannelException if the channel is closed
263      * @throws NotYetConnectedException if the channel is not yet connected
264      */
265     private void beginRead(boolean blocking) throws ClosedChannelException {
266         if (blocking) {
267             // set hook for Thread.interrupt
268             begin();
269         }
270         synchronized (stateLock) {
271             ensureOpen();
272             if (blocking)
273                 thread = NativeThread.current();

274         }
275     }
276 
277     /**
278      * Marks the end of a read operation that may have blocked.
279      *
280      * @throws AsynchronousCloseException if the channel was closed due to this
281      * thread being interrupted on a blocking read operation.
282      */
283     private void endRead(boolean blocking, boolean completed)
284         throws AsynchronousCloseException
285     {
286         if (blocking) {
287             synchronized (stateLock) {
288                 thread = 0;
289                 if (state == ST_CLOSING) {
290                     tryFinishClose();
291                 }
292             }
293             // remove hook for Thread.interrupt
294             end(completed);
295         }
296     }
297 
298     @Override
299     public int read(ByteBuffer dst) throws IOException {
300         Objects.requireNonNull(dst);
301 
302         readLock.lock();
303         try {
304             ensureOpen();
305             boolean blocking = isBlocking();
306             int n = 0;
307             try {
308                 beginRead(blocking);

 47     // The file descriptor associated with this channel
 48     private final FileDescriptor fd;
 49     private final int fdVal;
 50 
 51     // Lock held by current reading thread
 52     private final ReentrantLock readLock = new ReentrantLock();
 53 
 54     // Lock held by any thread that modifies the state fields declared below
 55     // DO NOT invoke a blocking I/O operation while holding this lock!
 56     private final Object stateLock = new Object();
 57 
 58     // -- The following fields are protected by stateLock
 59 
 60     // Channel state
 61     private static final int ST_INUSE = 0;
 62     private static final int ST_CLOSING = 1;
 63     private static final int ST_CLOSED = 2;
 64     private int state;
 65 
 66     // ID of native thread doing read, for signalling
 67     private NativeThread reader;
 68 
 69     // True if the channel's socket has been forced into non-blocking mode
 70     // by a virtual thread. It cannot be reset. When the channel is in
 71     // blocking mode and the channel's socket is in non-blocking mode then
 72     // operations that don't complete immediately will poll the socket and
 73     // preserve the semantics of blocking operations.
 74     private volatile boolean forcedNonBlocking;
 75 
 76     // -- End of fields protected by stateLock
 77 
 78 
 79     public FileDescriptor getFD() {
 80         return fd;
 81     }
 82 
 83     public int getFDVal() {
 84         return fdVal;
 85     }
 86 
 87     SourceChannelImpl(SelectorProvider sp, FileDescriptor fd) throws IOException {

103     /**
104      * Ensures that the socket is configured non-blocking when on a virtual thread.
105      */
106     private void configureSocketNonBlockingIfVirtualThread() throws IOException {
107         assert readLock.isHeldByCurrentThread();
108         if (!forcedNonBlocking && Thread.currentThread().isVirtual()) {
109             synchronized (stateLock) {
110                 ensureOpen();
111                 IOUtil.configureBlocking(fd, false);
112                 forcedNonBlocking = true;
113             }
114         }
115     }
116 
117     /**
118      * Closes the read end of the pipe if there are no read operation in
119      * progress and the channel is not registered with a Selector.
120      */
121     private boolean tryClose() throws IOException {
122         assert Thread.holdsLock(stateLock) && state == ST_CLOSING;
123         if (reader == null && !isRegistered()) {
124             state = ST_CLOSED;
125             nd.close(fd);
126             return true;
127         } else {
128             return false;
129         }
130     }
131 
132     /**
133      * Invokes tryClose to attempt to close the read end of the pipe.
134      *
135      * This method is used for deferred closing by I/O and Selector operations.
136      */
137     private void tryFinishClose() {
138         try {
139             tryClose();
140         } catch (IOException ignore) { }
141     }
142 
143     /**
144      * Closes this channel when configured in blocking mode.
145      *
146      * If there is a read operation in progress then the read-end of the pipe
147      * is pre-closed and the reader is signalled, in which case the final close
148      * is deferred until the reader aborts.
149      */
150     private void implCloseBlockingMode() throws IOException {
151         synchronized (stateLock) {
152             assert state < ST_CLOSING;
153             state = ST_CLOSING;
154             if (!tryClose()) {
155                 nd.preClose(fd, reader, null);
156             }
157         }
158     }
159 
160     /**
161      * Closes this channel when configured in non-blocking mode.
162      *
163      * If the channel is registered with a Selector then the close is deferred
164      * until the channel is flushed from all Selectors.
165      */
166     private void implCloseNonBlockingMode() throws IOException {
167         synchronized (stateLock) {
168             assert state < ST_CLOSING;
169             state = ST_CLOSING;
170         }
171         // wait for any read operation to complete before trying to close
172         readLock.lock();
173         readLock.unlock();
174         synchronized (stateLock) {
175             if (state == ST_CLOSING) {

252     public int translateInterestOps(int ops) {
253         int newOps = 0;
254         if (ops == SelectionKey.OP_READ)
255             newOps |= Net.POLLIN;
256         return newOps;
257     }
258 
259     /**
260      * Marks the beginning of a read operation that might block.
261      *
262      * @throws ClosedChannelException if the channel is closed
263      * @throws NotYetConnectedException if the channel is not yet connected
264      */
265     private void beginRead(boolean blocking) throws ClosedChannelException {
266         if (blocking) {
267             // set hook for Thread.interrupt
268             begin();
269         }
270         synchronized (stateLock) {
271             ensureOpen();
272             if (blocking) {
273                 reader = NativeThread.current();
274             }
275         }
276     }
277 
278     /**
279      * Marks the end of a read operation that may have blocked.
280      *
281      * @throws AsynchronousCloseException if the channel was closed due to this
282      * thread being interrupted on a blocking read operation.
283      */
284     private void endRead(boolean blocking, boolean completed)
285         throws AsynchronousCloseException
286     {
287         if (blocking) {
288             synchronized (stateLock) {
289                 reader = null;
290                 if (state == ST_CLOSING) {
291                     tryFinishClose();
292                 }
293             }
294             // remove hook for Thread.interrupt
295             end(completed);
296         }
297     }
298 
299     @Override
300     public int read(ByteBuffer dst) throws IOException {
301         Objects.requireNonNull(dst);
302 
303         readLock.lock();
304         try {
305             ensureOpen();
306             boolean blocking = isBlocking();
307             int n = 0;
308             try {
309                 beginRead(blocking);
< prev index next >