Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/nio/channels/spi/AbstractInterruptibleChannel.java
38918 views
1
/*
2
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
/*
27
*/
28
29
package java.nio.channels.spi;
30
31
import java.io.IOException;
32
import java.lang.reflect.Method;
33
import java.lang.reflect.InvocationTargetException;
34
import java.nio.channels.*;
35
import java.security.AccessController;
36
import java.security.PrivilegedAction;
37
import sun.nio.ch.Interruptible;
38
39
40
/**
41
* Base implementation class for interruptible channels.
42
*
43
* <p> This class encapsulates the low-level machinery required to implement
44
* the asynchronous closing and interruption of channels. A concrete channel
45
* class must invoke the {@link #begin begin} and {@link #end end} methods
46
* before and after, respectively, invoking an I/O operation that might block
47
* indefinitely. In order to ensure that the {@link #end end} method is always
48
* invoked, these methods should be used within a
49
* <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block:
50
*
51
* <blockquote><pre>
52
* boolean completed = false;
53
* try {
54
* begin();
55
* completed = ...; // Perform blocking I/O operation
56
* return ...; // Return result
57
* } finally {
58
* end(completed);
59
* }</pre></blockquote>
60
*
61
* <p> The <tt>completed</tt> argument to the {@link #end end} method tells
62
* whether or not the I/O operation actually completed, that is, whether it had
63
* any effect that would be visible to the invoker. In the case of an
64
* operation that reads bytes, for example, this argument should be
65
* <tt>true</tt> if, and only if, some bytes were actually transferred into the
66
* invoker's target buffer.
67
*
68
* <p> A concrete channel class must also implement the {@link
69
* #implCloseChannel implCloseChannel} method in such a way that if it is
70
* invoked while another thread is blocked in a native I/O operation upon the
71
* channel then that operation will immediately return, either by throwing an
72
* exception or by returning normally. If a thread is interrupted or the
73
* channel upon which it is blocked is asynchronously closed then the channel's
74
* {@link #end end} method will throw the appropriate exception.
75
*
76
* <p> This class performs the synchronization required to implement the {@link
77
* java.nio.channels.Channel} specification. Implementations of the {@link
78
* #implCloseChannel implCloseChannel} method need not synchronize against
79
* other threads that might be attempting to close the channel. </p>
80
*
81
*
82
* @author Mark Reinhold
83
* @author JSR-51 Expert Group
84
* @since 1.4
85
*/
86
87
public abstract class AbstractInterruptibleChannel
88
implements Channel, InterruptibleChannel
89
{
90
91
private final Object closeLock = new Object();
92
private volatile boolean open = true;
93
94
/**
95
* Initializes a new instance of this class.
96
*/
97
protected AbstractInterruptibleChannel() { }
98
99
/**
100
* Closes this channel.
101
*
102
* <p> If the channel has already been closed then this method returns
103
* immediately. Otherwise it marks the channel as closed and then invokes
104
* the {@link #implCloseChannel implCloseChannel} method in order to
105
* complete the close operation. </p>
106
*
107
* @throws IOException
108
* If an I/O error occurs
109
*/
110
public final void close() throws IOException {
111
synchronized (closeLock) {
112
if (!open)
113
return;
114
open = false;
115
implCloseChannel();
116
}
117
}
118
119
/**
120
* Closes this channel.
121
*
122
* <p> This method is invoked by the {@link #close close} method in order
123
* to perform the actual work of closing the channel. This method is only
124
* invoked if the channel has not yet been closed, and it is never invoked
125
* more than once.
126
*
127
* <p> An implementation of this method must arrange for any other thread
128
* that is blocked in an I/O operation upon this channel to return
129
* immediately, either by throwing an exception or by returning normally.
130
* </p>
131
*
132
* @throws IOException
133
* If an I/O error occurs while closing the channel
134
*/
135
protected abstract void implCloseChannel() throws IOException;
136
137
public final boolean isOpen() {
138
return open;
139
}
140
141
142
// -- Interruption machinery --
143
144
private Interruptible interruptor;
145
private volatile Thread interrupted;
146
147
/**
148
* Marks the beginning of an I/O operation that might block indefinitely.
149
*
150
* <p> This method should be invoked in tandem with the {@link #end end}
151
* method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
152
* shown <a href="#be">above</a>, in order to implement asynchronous
153
* closing and interruption for this channel. </p>
154
*/
155
protected final void begin() {
156
if (interruptor == null) {
157
interruptor = new Interruptible() {
158
public void interrupt(Thread target) {
159
synchronized (closeLock) {
160
if (!open)
161
return;
162
open = false;
163
interrupted = target;
164
try {
165
AbstractInterruptibleChannel.this.implCloseChannel();
166
} catch (IOException x) { }
167
}
168
}};
169
}
170
blockedOn(interruptor);
171
Thread me = Thread.currentThread();
172
if (me.isInterrupted())
173
interruptor.interrupt(me);
174
}
175
176
/**
177
* Marks the end of an I/O operation that might block indefinitely.
178
*
179
* <p> This method should be invoked in tandem with the {@link #begin
180
* begin} method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block
181
* as shown <a href="#be">above</a>, in order to implement asynchronous
182
* closing and interruption for this channel. </p>
183
*
184
* @param completed
185
* <tt>true</tt> if, and only if, the I/O operation completed
186
* successfully, that is, had some effect that would be visible to
187
* the operation's invoker
188
*
189
* @throws AsynchronousCloseException
190
* If the channel was asynchronously closed
191
*
192
* @throws ClosedByInterruptException
193
* If the thread blocked in the I/O operation was interrupted
194
*/
195
protected final void end(boolean completed)
196
throws AsynchronousCloseException
197
{
198
blockedOn(null);
199
Thread interrupted = this.interrupted;
200
if (interrupted != null && interrupted == Thread.currentThread()) {
201
interrupted = null;
202
throw new ClosedByInterruptException();
203
}
204
if (!completed && !open)
205
throw new AsynchronousCloseException();
206
}
207
208
209
// -- sun.misc.SharedSecrets --
210
static void blockedOn(Interruptible intr) { // package-private
211
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(),
212
intr);
213
}
214
}
215
216