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/AbstractSelectableChannel.java
38918 views
1
/*
2
* Copyright (c) 2000, 2018, 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
package java.nio.channels.spi;
27
28
import java.io.IOException;
29
import java.nio.channels.CancelledKeyException;
30
import java.nio.channels.ClosedChannelException;
31
import java.nio.channels.ClosedSelectorException;
32
import java.nio.channels.IllegalBlockingModeException;
33
import java.nio.channels.IllegalSelectorException;
34
import java.nio.channels.SelectableChannel;
35
import java.nio.channels.SelectionKey;
36
import java.nio.channels.Selector;
37
38
39
/**
40
* Base implementation class for selectable channels.
41
*
42
* <p> This class defines methods that handle the mechanics of channel
43
* registration, deregistration, and closing. It maintains the current
44
* blocking mode of this channel as well as its current set of selection keys.
45
* It performs all of the synchronization required to implement the {@link
46
* java.nio.channels.SelectableChannel} specification. Implementations of the
47
* abstract protected methods defined in this class need not synchronize
48
* against other threads that might be engaged in the same operations. </p>
49
*
50
*
51
* @author Mark Reinhold
52
* @author Mike McCloskey
53
* @author JSR-51 Expert Group
54
* @since 1.4
55
*/
56
57
public abstract class AbstractSelectableChannel
58
extends SelectableChannel
59
{
60
61
// The provider that created this channel
62
private final SelectorProvider provider;
63
64
// Keys that have been created by registering this channel with selectors.
65
// They are saved because if this channel is closed the keys must be
66
// deregistered. Protected by keyLock.
67
//
68
private SelectionKey[] keys = null;
69
private int keyCount = 0;
70
71
// Lock for key set and count
72
private final Object keyLock = new Object();
73
74
// Lock for registration and configureBlocking operations
75
private final Object regLock = new Object();
76
77
// True when non-blocking, need regLock to change;
78
private volatile boolean nonBlocking;
79
80
/**
81
* Initializes a new instance of this class.
82
*
83
* @param provider
84
* The provider that created this channel
85
*/
86
protected AbstractSelectableChannel(SelectorProvider provider) {
87
this.provider = provider;
88
}
89
90
/**
91
* Returns the provider that created this channel.
92
*
93
* @return The provider that created this channel
94
*/
95
public final SelectorProvider provider() {
96
return provider;
97
}
98
99
100
// -- Utility methods for the key set --
101
102
private void addKey(SelectionKey k) {
103
assert Thread.holdsLock(keyLock);
104
int i = 0;
105
if ((keys != null) && (keyCount < keys.length)) {
106
// Find empty element of key array
107
for (i = 0; i < keys.length; i++)
108
if (keys[i] == null)
109
break;
110
} else if (keys == null) {
111
keys = new SelectionKey[3];
112
} else {
113
// Grow key array
114
int n = keys.length * 2;
115
SelectionKey[] ks = new SelectionKey[n];
116
for (i = 0; i < keys.length; i++)
117
ks[i] = keys[i];
118
keys = ks;
119
i = keyCount;
120
}
121
keys[i] = k;
122
keyCount++;
123
}
124
125
private SelectionKey findKey(Selector sel) {
126
synchronized (keyLock) {
127
if (keys == null)
128
return null;
129
for (int i = 0; i < keys.length; i++)
130
if ((keys[i] != null) && (keys[i].selector() == sel))
131
return keys[i];
132
return null;
133
}
134
}
135
136
void removeKey(SelectionKey k) { // package-private
137
synchronized (keyLock) {
138
for (int i = 0; i < keys.length; i++)
139
if (keys[i] == k) {
140
keys[i] = null;
141
keyCount--;
142
}
143
((AbstractSelectionKey)k).invalidate();
144
}
145
}
146
147
private boolean haveValidKeys() {
148
synchronized (keyLock) {
149
if (keyCount == 0)
150
return false;
151
for (int i = 0; i < keys.length; i++) {
152
if ((keys[i] != null) && keys[i].isValid())
153
return true;
154
}
155
return false;
156
}
157
}
158
159
160
// -- Registration --
161
162
public final boolean isRegistered() {
163
synchronized (keyLock) {
164
return keyCount != 0;
165
}
166
}
167
168
public final SelectionKey keyFor(Selector sel) {
169
return findKey(sel);
170
}
171
172
/**
173
* Registers this channel with the given selector, returning a selection key.
174
*
175
* <p> This method first verifies that this channel is open and that the
176
* given initial interest set is valid.
177
*
178
* <p> If this channel is already registered with the given selector then
179
* the selection key representing that registration is returned after
180
* setting its interest set to the given value.
181
*
182
* <p> Otherwise this channel has not yet been registered with the given
183
* selector, so the {@link AbstractSelector#register register} method of
184
* the selector is invoked while holding the appropriate locks. The
185
* resulting key is added to this channel's key set before being returned.
186
* </p>
187
*
188
* @throws ClosedSelectorException {@inheritDoc}
189
*
190
* @throws IllegalBlockingModeException {@inheritDoc}
191
*
192
* @throws IllegalSelectorException {@inheritDoc}
193
*
194
* @throws CancelledKeyException {@inheritDoc}
195
*
196
* @throws IllegalArgumentException {@inheritDoc}
197
*/
198
public final SelectionKey register(Selector sel, int ops,
199
Object att)
200
throws ClosedChannelException
201
{
202
synchronized (regLock) {
203
if (!isOpen())
204
throw new ClosedChannelException();
205
if ((ops & ~validOps()) != 0)
206
throw new IllegalArgumentException();
207
if (isBlocking())
208
throw new IllegalBlockingModeException();
209
SelectionKey k = findKey(sel);
210
if (k != null) {
211
k.interestOps(ops);
212
k.attach(att);
213
}
214
if (k == null) {
215
// New registration
216
synchronized (keyLock) {
217
if (!isOpen())
218
throw new ClosedChannelException();
219
k = ((AbstractSelector)sel).register(this, ops, att);
220
addKey(k);
221
}
222
}
223
return k;
224
}
225
}
226
227
228
// -- Closing --
229
230
/**
231
* Closes this channel.
232
*
233
* <p> This method, which is specified in the {@link
234
* AbstractInterruptibleChannel} class and is invoked by the {@link
235
* java.nio.channels.Channel#close close} method, in turn invokes the
236
* {@link #implCloseSelectableChannel implCloseSelectableChannel} method in
237
* order to perform the actual work of closing this channel. It then
238
* cancels all of this channel's keys. </p>
239
*/
240
protected final void implCloseChannel() throws IOException {
241
implCloseSelectableChannel();
242
synchronized (keyLock) {
243
int count = (keys == null) ? 0 : keys.length;
244
for (int i = 0; i < count; i++) {
245
SelectionKey k = keys[i];
246
if (k != null)
247
k.cancel();
248
}
249
}
250
}
251
252
/**
253
* Closes this selectable channel.
254
*
255
* <p> This method is invoked by the {@link java.nio.channels.Channel#close
256
* close} method in order to perform the actual work of closing the
257
* channel. This method is only invoked if the channel has not yet been
258
* closed, and it is never invoked more than once.
259
*
260
* <p> An implementation of this method must arrange for any other thread
261
* that is blocked in an I/O operation upon this channel to return
262
* immediately, either by throwing an exception or by returning normally.
263
* </p>
264
*
265
* @throws IOException
266
* If an I/O error occurs
267
*/
268
protected abstract void implCloseSelectableChannel() throws IOException;
269
270
271
// -- Blocking --
272
273
public final boolean isBlocking() {
274
return !nonBlocking;
275
}
276
277
public final Object blockingLock() {
278
return regLock;
279
}
280
281
/**
282
* Adjusts this channel's blocking mode.
283
*
284
* <p> If the given blocking mode is different from the current blocking
285
* mode then this method invokes the {@link #implConfigureBlocking
286
* implConfigureBlocking} method, while holding the appropriate locks, in
287
* order to change the mode. </p>
288
*/
289
public final SelectableChannel configureBlocking(boolean block)
290
throws IOException
291
{
292
synchronized (regLock) {
293
if (!isOpen())
294
throw new ClosedChannelException();
295
boolean blocking = !nonBlocking;
296
if (block != blocking) {
297
if (block && haveValidKeys())
298
throw new IllegalBlockingModeException();
299
implConfigureBlocking(block);
300
nonBlocking = !block;
301
}
302
}
303
return this;
304
}
305
306
/**
307
* Adjusts this channel's blocking mode.
308
*
309
* <p> This method is invoked by the {@link #configureBlocking
310
* configureBlocking} method in order to perform the actual work of
311
* changing the blocking mode. This method is only invoked if the new mode
312
* is different from the current mode. </p>
313
*
314
* @param block If <tt>true</tt> then this channel will be placed in
315
* blocking mode; if <tt>false</tt> then it will be placed
316
* non-blocking mode
317
*
318
* @throws IOException
319
* If an I/O error occurs
320
*/
321
protected abstract void implConfigureBlocking(boolean block)
322
throws IOException;
323
324
}
325
326