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