Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java
41159 views
1
/*
2
* Copyright (c) 2000, 2019, 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 sun.nio.ch;
27
28
import java.io.IOException;
29
import java.nio.channels.ClosedSelectorException;
30
import java.nio.channels.IllegalSelectorException;
31
import java.nio.channels.SelectableChannel;
32
import java.nio.channels.SelectionKey;
33
import java.nio.channels.spi.AbstractSelectableChannel;
34
import java.nio.channels.spi.AbstractSelector;
35
import java.nio.channels.spi.SelectorProvider;
36
import java.util.ArrayDeque;
37
import java.util.Collections;
38
import java.util.Deque;
39
import java.util.HashSet;
40
import java.util.Iterator;
41
import java.util.Objects;
42
import java.util.Set;
43
import java.util.concurrent.ConcurrentHashMap;
44
import java.util.function.Consumer;
45
46
47
/**
48
* Base Selector implementation class.
49
*/
50
51
public abstract class SelectorImpl
52
extends AbstractSelector
53
{
54
// The set of keys registered with this Selector
55
private final Set<SelectionKey> keys;
56
57
// The set of keys with data ready for an operation
58
private final Set<SelectionKey> selectedKeys;
59
60
// Public views of the key sets
61
private final Set<SelectionKey> publicKeys; // Immutable
62
private final Set<SelectionKey> publicSelectedKeys; // Removal allowed, but not addition
63
64
// pending cancelled keys for deregistration
65
private final Deque<SelectionKeyImpl> cancelledKeys = new ArrayDeque<>();
66
67
// used to check for reentrancy
68
private boolean inSelect;
69
70
protected SelectorImpl(SelectorProvider sp) {
71
super(sp);
72
keys = ConcurrentHashMap.newKeySet();
73
selectedKeys = new HashSet<>();
74
publicKeys = Collections.unmodifiableSet(keys);
75
publicSelectedKeys = Util.ungrowableSet(selectedKeys);
76
}
77
78
private void ensureOpen() {
79
if (!isOpen())
80
throw new ClosedSelectorException();
81
}
82
83
@Override
84
public final Set<SelectionKey> keys() {
85
ensureOpen();
86
return publicKeys;
87
}
88
89
@Override
90
public final Set<SelectionKey> selectedKeys() {
91
ensureOpen();
92
return publicSelectedKeys;
93
}
94
95
/**
96
* Marks the beginning of a select operation that might block
97
*/
98
protected final void begin(boolean blocking) {
99
if (blocking) begin();
100
}
101
102
/**
103
* Marks the end of a select operation that may have blocked
104
*/
105
protected final void end(boolean blocking) {
106
if (blocking) end();
107
}
108
109
/**
110
* Selects the keys for channels that are ready for I/O operations.
111
*
112
* @param action the action to perform, can be null
113
* @param timeout timeout in milliseconds to wait, 0 to not wait, -1 to
114
* wait indefinitely
115
*/
116
protected abstract int doSelect(Consumer<SelectionKey> action, long timeout)
117
throws IOException;
118
119
private int lockAndDoSelect(Consumer<SelectionKey> action, long timeout)
120
throws IOException
121
{
122
synchronized (this) {
123
ensureOpen();
124
if (inSelect)
125
throw new IllegalStateException("select in progress");
126
inSelect = true;
127
try {
128
synchronized (publicSelectedKeys) {
129
return doSelect(action, timeout);
130
}
131
} finally {
132
inSelect = false;
133
}
134
}
135
}
136
137
@Override
138
public final int select(long timeout) throws IOException {
139
if (timeout < 0)
140
throw new IllegalArgumentException("Negative timeout");
141
return lockAndDoSelect(null, (timeout == 0) ? -1 : timeout);
142
}
143
144
@Override
145
public final int select() throws IOException {
146
return lockAndDoSelect(null, -1);
147
}
148
149
@Override
150
public final int selectNow() throws IOException {
151
return lockAndDoSelect(null, 0);
152
}
153
154
@Override
155
public final int select(Consumer<SelectionKey> action, long timeout)
156
throws IOException
157
{
158
Objects.requireNonNull(action);
159
if (timeout < 0)
160
throw new IllegalArgumentException("Negative timeout");
161
return lockAndDoSelect(action, (timeout == 0) ? -1 : timeout);
162
}
163
164
@Override
165
public final int select(Consumer<SelectionKey> action) throws IOException {
166
Objects.requireNonNull(action);
167
return lockAndDoSelect(action, -1);
168
}
169
170
@Override
171
public final int selectNow(Consumer<SelectionKey> action) throws IOException {
172
Objects.requireNonNull(action);
173
return lockAndDoSelect(action, 0);
174
}
175
176
/**
177
* Invoked by implCloseSelector to close the selector.
178
*/
179
protected abstract void implClose() throws IOException;
180
181
@Override
182
public final void implCloseSelector() throws IOException {
183
wakeup();
184
synchronized (this) {
185
implClose();
186
synchronized (publicSelectedKeys) {
187
// Deregister channels
188
Iterator<SelectionKey> i = keys.iterator();
189
while (i.hasNext()) {
190
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
191
deregister(ski);
192
SelectableChannel selch = ski.channel();
193
if (!selch.isOpen() && !selch.isRegistered())
194
((SelChImpl)selch).kill();
195
selectedKeys.remove(ski);
196
i.remove();
197
}
198
assert selectedKeys.isEmpty() && keys.isEmpty();
199
}
200
}
201
}
202
203
@Override
204
protected final SelectionKey register(AbstractSelectableChannel ch,
205
int ops,
206
Object attachment)
207
{
208
if (!(ch instanceof SelChImpl))
209
throw new IllegalSelectorException();
210
SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
211
if (attachment != null)
212
k.attach(attachment);
213
214
// register (if needed) before adding to key set
215
implRegister(k);
216
217
// add to the selector's key set, removing it immediately if the selector
218
// is closed. The key is not in the channel's key set at this point but
219
// it may be observed by a thread iterating over the selector's key set.
220
keys.add(k);
221
try {
222
k.interestOps(ops);
223
} catch (ClosedSelectorException e) {
224
assert ch.keyFor(this) == null;
225
keys.remove(k);
226
k.cancel();
227
throw e;
228
}
229
return k;
230
}
231
232
/**
233
* Register the key in the selector.
234
*
235
* The default implementation checks if the selector is open. It should
236
* be overridden by selector implementations as needed.
237
*/
238
protected void implRegister(SelectionKeyImpl ski) {
239
ensureOpen();
240
}
241
242
/**
243
* Removes the key from the selector
244
*/
245
protected abstract void implDereg(SelectionKeyImpl ski) throws IOException;
246
247
/**
248
* Queue a cancelled key for the next selection operation
249
*/
250
public void cancel(SelectionKeyImpl ski) {
251
synchronized (cancelledKeys) {
252
cancelledKeys.addLast(ski);
253
}
254
}
255
256
/**
257
* Invoked by selection operations to process the cancelled keys
258
*/
259
protected final void processDeregisterQueue() throws IOException {
260
assert Thread.holdsLock(this);
261
assert Thread.holdsLock(publicSelectedKeys);
262
263
synchronized (cancelledKeys) {
264
SelectionKeyImpl ski;
265
while ((ski = cancelledKeys.pollFirst()) != null) {
266
// remove the key from the selector
267
implDereg(ski);
268
269
selectedKeys.remove(ski);
270
keys.remove(ski);
271
272
// remove from channel's key set
273
deregister(ski);
274
275
SelectableChannel ch = ski.channel();
276
if (!ch.isOpen() && !ch.isRegistered())
277
((SelChImpl)ch).kill();
278
}
279
}
280
}
281
282
/**
283
* Invoked by selection operations to handle ready events. If an action
284
* is specified then it is invoked to handle the key, otherwise the key
285
* is added to the selected-key set (or updated when it is already in the
286
* set).
287
*/
288
protected final int processReadyEvents(int rOps,
289
SelectionKeyImpl ski,
290
Consumer<SelectionKey> action) {
291
if (action != null) {
292
ski.translateAndSetReadyOps(rOps);
293
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
294
action.accept(ski);
295
ensureOpen();
296
return 1;
297
}
298
} else {
299
assert Thread.holdsLock(publicSelectedKeys);
300
if (selectedKeys.contains(ski)) {
301
if (ski.translateAndUpdateReadyOps(rOps)) {
302
return 1;
303
}
304
} else {
305
ski.translateAndSetReadyOps(rOps);
306
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
307
selectedKeys.add(ski);
308
return 1;
309
}
310
}
311
}
312
return 0;
313
}
314
315
/**
316
* Invoked by interestOps to ensure the interest ops are updated at the
317
* next selection operation.
318
*/
319
protected abstract void setEventOps(SelectionKeyImpl ski);
320
}
321
322