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/fs/AbstractPoller.java
38918 views
1
/*
2
* Copyright (c) 2008, 2014, 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.fs;
27
28
import java.nio.file.*;
29
import java.security.AccessController;
30
import java.security.PrivilegedAction;
31
import java.io.IOException;
32
import java.util.*;
33
34
/**
35
* Base implementation of background poller thread used in watch service
36
* implementations. A poller thread waits on events from the file system and
37
* also services "requests" from clients to register for new events or cancel
38
* existing registrations.
39
*/
40
41
abstract class AbstractPoller implements Runnable {
42
43
// list of requests pending to the poller thread
44
private final LinkedList<Request> requestList;
45
46
// set to true when shutdown
47
private boolean shutdown;
48
49
protected AbstractPoller() {
50
this.requestList = new LinkedList<Request>();
51
this.shutdown = false;
52
}
53
54
/**
55
* Starts the poller thread
56
*/
57
public void start() {
58
final Runnable thisRunnable = this;
59
AccessController.doPrivileged(new PrivilegedAction<Object>() {
60
@Override
61
public Object run() {
62
Thread thr = new Thread(thisRunnable);
63
thr.setDaemon(true);
64
thr.start();
65
return null;
66
}
67
});
68
}
69
70
/**
71
* Wakeup poller thread so that it can service pending requests
72
*/
73
abstract void wakeup() throws IOException;
74
75
/**
76
* Executed by poller thread to register directory for changes
77
*/
78
abstract Object implRegister(Path path,
79
Set<? extends WatchEvent.Kind<?>> events,
80
WatchEvent.Modifier... modifiers);
81
82
/**
83
* Executed by poller thread to cancel key
84
*/
85
abstract void implCancelKey(WatchKey key);
86
87
/**
88
* Executed by poller thread to shutdown and cancel all keys
89
*/
90
abstract void implCloseAll();
91
92
/**
93
* Requests, and waits on, poller thread to register given file.
94
*/
95
final WatchKey register(Path dir,
96
WatchEvent.Kind<?>[] events,
97
WatchEvent.Modifier... modifiers)
98
throws IOException
99
{
100
// validate arguments before request to poller
101
if (dir == null)
102
throw new NullPointerException();
103
Set<WatchEvent.Kind<?>> eventSet = new HashSet<>(events.length);
104
for (WatchEvent.Kind<?> event: events) {
105
// standard events
106
if (event == StandardWatchEventKinds.ENTRY_CREATE ||
107
event == StandardWatchEventKinds.ENTRY_MODIFY ||
108
event == StandardWatchEventKinds.ENTRY_DELETE)
109
{
110
eventSet.add(event);
111
continue;
112
}
113
114
// OVERFLOW is ignored
115
if (event == StandardWatchEventKinds.OVERFLOW)
116
continue;
117
118
// null/unsupported
119
if (event == null)
120
throw new NullPointerException("An element in event set is 'null'");
121
throw new UnsupportedOperationException(event.name());
122
}
123
if (eventSet.isEmpty())
124
throw new IllegalArgumentException("No events to register");
125
return (WatchKey)invoke(RequestType.REGISTER, dir, eventSet, modifiers);
126
}
127
128
/**
129
* Cancels, and waits on, poller thread to cancel given key.
130
*/
131
final void cancel(WatchKey key) {
132
try {
133
invoke(RequestType.CANCEL, key);
134
} catch (IOException x) {
135
// should not happen
136
throw new AssertionError(x.getMessage());
137
}
138
}
139
140
/**
141
* Shutdown poller thread
142
*/
143
final void close() throws IOException {
144
invoke(RequestType.CLOSE);
145
}
146
147
/**
148
* Types of request that the poller thread must handle
149
*/
150
private static enum RequestType {
151
REGISTER,
152
CANCEL,
153
CLOSE;
154
}
155
156
/**
157
* Encapsulates a request (command) to the poller thread.
158
*/
159
private static class Request {
160
private final RequestType type;
161
private final Object[] params;
162
163
private boolean completed = false;
164
private Object result = null;
165
166
Request(RequestType type, Object... params) {
167
this.type = type;
168
this.params = params;
169
}
170
171
RequestType type() {
172
return type;
173
}
174
175
Object[] parameters() {
176
return params;
177
}
178
179
void release(Object result) {
180
synchronized (this) {
181
this.completed = true;
182
this.result = result;
183
notifyAll();
184
}
185
}
186
187
/**
188
* Await completion of the request. The return value is the result of
189
* the request.
190
*/
191
Object awaitResult() {
192
boolean interrupted = false;
193
synchronized (this) {
194
while (!completed) {
195
try {
196
wait();
197
} catch (InterruptedException x) {
198
interrupted = true;
199
}
200
}
201
if (interrupted)
202
Thread.currentThread().interrupt();
203
return result;
204
}
205
}
206
}
207
208
/**
209
* Enqueues request to poller thread and waits for result
210
*/
211
private Object invoke(RequestType type, Object... params) throws IOException {
212
// submit request
213
Request req = new Request(type, params);
214
synchronized (requestList) {
215
if (shutdown) {
216
throw new ClosedWatchServiceException();
217
}
218
requestList.add(req);
219
}
220
221
// wakeup thread
222
wakeup();
223
224
// wait for result
225
Object result = req.awaitResult();
226
227
if (result instanceof RuntimeException)
228
throw (RuntimeException)result;
229
if (result instanceof IOException )
230
throw (IOException)result;
231
return result;
232
}
233
234
/**
235
* Invoked by poller thread to process all pending requests
236
*
237
* @return true if poller thread should shutdown
238
*/
239
@SuppressWarnings("unchecked")
240
boolean processRequests() {
241
synchronized (requestList) {
242
Request req;
243
while ((req = requestList.poll()) != null) {
244
// if in process of shutdown then reject request
245
if (shutdown) {
246
req.release(new ClosedWatchServiceException());
247
}
248
249
switch (req.type()) {
250
/**
251
* Register directory
252
*/
253
case REGISTER: {
254
Object[] params = req.parameters();
255
Path path = (Path)params[0];
256
Set<? extends WatchEvent.Kind<?>> events =
257
(Set<? extends WatchEvent.Kind<?>>)params[1];
258
WatchEvent.Modifier[] modifiers =
259
(WatchEvent.Modifier[])params[2];
260
req.release(implRegister(path, events, modifiers));
261
break;
262
}
263
/**
264
* Cancel existing key
265
*/
266
case CANCEL : {
267
Object[] params = req.parameters();
268
WatchKey key = (WatchKey)params[0];
269
implCancelKey(key);
270
req.release(null);
271
break;
272
}
273
/**
274
* Close watch service
275
*/
276
case CLOSE: {
277
implCloseAll();
278
req.release(null);
279
shutdown = true;
280
break;
281
}
282
283
default:
284
req.release(new IOException("request not recognized"));
285
}
286
}
287
}
288
return shutdown;
289
}
290
}
291
292