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/sun/nio/ch/Invoker.java
38918 views
1
/*
2
* Copyright (c) 2008, 2009, 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.nio.channels.*;
29
import java.util.concurrent.*;
30
import java.security.AccessController;
31
import sun.security.action.GetIntegerAction;
32
33
/**
34
* Defines static methods to invoke a completion handler or arbitrary task.
35
*/
36
37
class Invoker {
38
private Invoker() { }
39
40
// maximum number of completion handlers that may be invoked on the current
41
// thread before it re-directs invocations to the thread pool. This helps
42
// avoid stack overflow and lessens the risk of starvation.
43
private static final int maxHandlerInvokeCount = AccessController.doPrivileged(
44
new GetIntegerAction("sun.nio.ch.maxCompletionHandlersOnStack", 16));
45
46
// Per-thread object with reference to channel group and a counter for
47
// the number of completion handlers invoked. This should be reset to 0
48
// when all completion handlers have completed.
49
static class GroupAndInvokeCount {
50
private final AsynchronousChannelGroupImpl group;
51
private int handlerInvokeCount;
52
GroupAndInvokeCount(AsynchronousChannelGroupImpl group) {
53
this.group = group;
54
}
55
AsynchronousChannelGroupImpl group() {
56
return group;
57
}
58
int invokeCount() {
59
return handlerInvokeCount;
60
}
61
void setInvokeCount(int value) {
62
handlerInvokeCount = value;
63
}
64
void resetInvokeCount() {
65
handlerInvokeCount = 0;
66
}
67
void incrementInvokeCount() {
68
handlerInvokeCount++;
69
}
70
}
71
private static final ThreadLocal<GroupAndInvokeCount> myGroupAndInvokeCount =
72
new ThreadLocal<GroupAndInvokeCount>() {
73
@Override protected GroupAndInvokeCount initialValue() {
74
return null;
75
}
76
};
77
78
/**
79
* Binds this thread to the given group
80
*/
81
static void bindToGroup(AsynchronousChannelGroupImpl group) {
82
myGroupAndInvokeCount.set(new GroupAndInvokeCount(group));
83
}
84
85
/**
86
* Returns the GroupAndInvokeCount object for this thread.
87
*/
88
static GroupAndInvokeCount getGroupAndInvokeCount() {
89
return myGroupAndInvokeCount.get();
90
}
91
92
/**
93
* Returns true if the current thread is in a channel group's thread pool
94
*/
95
static boolean isBoundToAnyGroup() {
96
return myGroupAndInvokeCount.get() != null;
97
}
98
99
/**
100
* Returns true if the current thread is in the given channel's thread
101
* pool and we haven't exceeded the maximum number of handler frames on
102
* the stack.
103
*/
104
static boolean mayInvokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
105
AsynchronousChannelGroupImpl group)
106
{
107
if ((myGroupAndInvokeCount != null) &&
108
(myGroupAndInvokeCount.group() == group) &&
109
(myGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
110
{
111
return true;
112
}
113
return false;
114
}
115
116
/**
117
* Invoke handler without checking the thread identity or number of handlers
118
* on the thread stack.
119
*/
120
static <V,A> void invokeUnchecked(CompletionHandler<V,? super A> handler,
121
A attachment,
122
V value,
123
Throwable exc)
124
{
125
if (exc == null) {
126
handler.completed(value, attachment);
127
} else {
128
handler.failed(exc, attachment);
129
}
130
131
// clear interrupt
132
Thread.interrupted();
133
134
// clear thread locals when in default thread pool
135
if (System.getSecurityManager() != null) {
136
Thread me = Thread.currentThread();
137
if (me instanceof sun.misc.InnocuousThread) {
138
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
139
((sun.misc.InnocuousThread)me).eraseThreadLocals();
140
if (thisGroupAndInvokeCount != null) {
141
myGroupAndInvokeCount.set(thisGroupAndInvokeCount);
142
}
143
}
144
}
145
}
146
147
/**
148
* Invoke handler assuming thread identity already checked
149
*/
150
static <V,A> void invokeDirect(GroupAndInvokeCount myGroupAndInvokeCount,
151
CompletionHandler<V,? super A> handler,
152
A attachment,
153
V result,
154
Throwable exc)
155
{
156
myGroupAndInvokeCount.incrementInvokeCount();
157
Invoker.invokeUnchecked(handler, attachment, result, exc);
158
}
159
160
/**
161
* Invokes the handler. If the current thread is in the channel group's
162
* thread pool then the handler is invoked directly, otherwise it is
163
* invoked indirectly.
164
*/
165
static <V,A> void invoke(AsynchronousChannel channel,
166
CompletionHandler<V,? super A> handler,
167
A attachment,
168
V result,
169
Throwable exc)
170
{
171
boolean invokeDirect = false;
172
boolean identityOkay = false;
173
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
174
if (thisGroupAndInvokeCount != null) {
175
if ((thisGroupAndInvokeCount.group() == ((Groupable)channel).group()))
176
identityOkay = true;
177
if (identityOkay &&
178
(thisGroupAndInvokeCount.invokeCount() < maxHandlerInvokeCount))
179
{
180
// group match
181
invokeDirect = true;
182
}
183
}
184
if (invokeDirect) {
185
invokeDirect(thisGroupAndInvokeCount, handler, attachment, result, exc);
186
} else {
187
try {
188
invokeIndirectly(channel, handler, attachment, result, exc);
189
} catch (RejectedExecutionException ree) {
190
// channel group shutdown; fallback to invoking directly
191
// if the current thread has the right identity.
192
if (identityOkay) {
193
invokeDirect(thisGroupAndInvokeCount,
194
handler, attachment, result, exc);
195
} else {
196
throw new ShutdownChannelGroupException();
197
}
198
}
199
}
200
}
201
202
/**
203
* Invokes the handler indirectly via the channel group's thread pool.
204
*/
205
static <V,A> void invokeIndirectly(AsynchronousChannel channel,
206
final CompletionHandler<V,? super A> handler,
207
final A attachment,
208
final V result,
209
final Throwable exc)
210
{
211
try {
212
((Groupable)channel).group().executeOnPooledThread(new Runnable() {
213
public void run() {
214
GroupAndInvokeCount thisGroupAndInvokeCount =
215
myGroupAndInvokeCount.get();
216
if (thisGroupAndInvokeCount != null)
217
thisGroupAndInvokeCount.setInvokeCount(1);
218
invokeUnchecked(handler, attachment, result, exc);
219
}
220
});
221
} catch (RejectedExecutionException ree) {
222
throw new ShutdownChannelGroupException();
223
}
224
}
225
226
/**
227
* Invokes the handler "indirectly" in the given Executor
228
*/
229
static <V,A> void invokeIndirectly(final CompletionHandler<V,? super A> handler,
230
final A attachment,
231
final V value,
232
final Throwable exc,
233
Executor executor)
234
{
235
try {
236
executor.execute(new Runnable() {
237
public void run() {
238
invokeUnchecked(handler, attachment, value, exc);
239
}
240
});
241
} catch (RejectedExecutionException ree) {
242
throw new ShutdownChannelGroupException();
243
}
244
}
245
246
/**
247
* Invokes the given task on the thread pool associated with the given
248
* channel. If the current thread is in the thread pool then the task is
249
* invoked directly.
250
*/
251
static void invokeOnThreadInThreadPool(Groupable channel,
252
Runnable task)
253
{
254
boolean invokeDirect;
255
GroupAndInvokeCount thisGroupAndInvokeCount = myGroupAndInvokeCount.get();
256
AsynchronousChannelGroupImpl targetGroup = channel.group();
257
if (thisGroupAndInvokeCount == null) {
258
invokeDirect = false;
259
} else {
260
invokeDirect = (thisGroupAndInvokeCount.group == targetGroup);
261
}
262
try {
263
if (invokeDirect) {
264
task.run();
265
} else {
266
targetGroup.executeOnPooledThread(task);
267
}
268
} catch (RejectedExecutionException ree) {
269
throw new ShutdownChannelGroupException();
270
}
271
}
272
273
/**
274
* Invoke handler with completed result. This method does not check the
275
* thread identity or the number of handlers on the thread stack.
276
*/
277
static <V,A> void invokeUnchecked(PendingFuture<V,A> future) {
278
assert future.isDone();
279
CompletionHandler<V,? super A> handler = future.handler();
280
if (handler != null) {
281
invokeUnchecked(handler,
282
future.attachment(),
283
future.value(),
284
future.exception());
285
}
286
}
287
288
/**
289
* Invoke handler with completed result. If the current thread is in the
290
* channel group's thread pool then the handler is invoked directly,
291
* otherwise it is invoked indirectly.
292
*/
293
static <V,A> void invoke(PendingFuture<V,A> future) {
294
assert future.isDone();
295
CompletionHandler<V,? super A> handler = future.handler();
296
if (handler != null) {
297
invoke(future.channel(),
298
handler,
299
future.attachment(),
300
future.value(),
301
future.exception());
302
}
303
}
304
305
/**
306
* Invoke handler with completed result. The handler is invoked indirectly,
307
* via the channel group's thread pool.
308
*/
309
static <V,A> void invokeIndirectly(PendingFuture<V,A> future) {
310
assert future.isDone();
311
CompletionHandler<V,? super A> handler = future.handler();
312
if (handler != null) {
313
invokeIndirectly(future.channel(),
314
handler,
315
future.attachment(),
316
future.value(),
317
future.exception());
318
}
319
}
320
}
321
322