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/AbstractWatchKey.java
41159 views
1
/*
2
* Copyright (c) 2008, 2011, 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.util.*;
30
31
/**
32
* Base implementation class for watch keys.
33
*/
34
35
abstract class AbstractWatchKey implements WatchKey {
36
37
/**
38
* Maximum size of event list (in the future this may be tunable)
39
*/
40
static final int MAX_EVENT_LIST_SIZE = 512;
41
42
/**
43
* Special event to signal overflow
44
*/
45
static final Event<Object> OVERFLOW_EVENT =
46
new Event<Object>(StandardWatchEventKinds.OVERFLOW, null);
47
48
/**
49
* Possible key states
50
*/
51
private static enum State { READY, SIGNALLED };
52
53
// reference to watcher
54
private final AbstractWatchService watcher;
55
56
// reference to the original directory
57
private final Path dir;
58
59
// key state
60
private State state;
61
62
// pending events
63
private List<WatchEvent<?>> events;
64
65
// maps a context to the last event for the context (iff the last queued
66
// event for the context is an ENTRY_MODIFY event).
67
private Map<Object,WatchEvent<?>> lastModifyEvents;
68
69
protected AbstractWatchKey(Path dir, AbstractWatchService watcher) {
70
this.watcher = watcher;
71
this.dir = dir;
72
this.state = State.READY;
73
this.events = new ArrayList<>();
74
this.lastModifyEvents = new HashMap<>();
75
}
76
77
final AbstractWatchService watcher() {
78
return watcher;
79
}
80
81
/**
82
* Return the original watchable (Path)
83
*/
84
@Override
85
public Path watchable() {
86
return dir;
87
}
88
89
/**
90
* Enqueues this key to the watch service
91
*/
92
final void signal() {
93
synchronized (this) {
94
if (state == State.READY) {
95
state = State.SIGNALLED;
96
watcher.enqueueKey(this);
97
}
98
}
99
}
100
101
/**
102
* Adds the event to this key and signals it.
103
*/
104
@SuppressWarnings("unchecked")
105
final void signalEvent(WatchEvent.Kind<?> kind, Object context) {
106
boolean isModify = (kind == StandardWatchEventKinds.ENTRY_MODIFY);
107
synchronized (this) {
108
int size = events.size();
109
if (size > 0) {
110
// if the previous event is an OVERFLOW event or this is a
111
// repeated event then we simply increment the counter
112
WatchEvent<?> prev = events.get(size-1);
113
if ((prev.kind() == StandardWatchEventKinds.OVERFLOW) ||
114
((kind == prev.kind() &&
115
Objects.equals(context, prev.context()))))
116
{
117
((Event<?>)prev).increment();
118
return;
119
}
120
121
// if this is a modify event and the last entry for the context
122
// is a modify event then we simply increment the count
123
if (!lastModifyEvents.isEmpty()) {
124
if (isModify) {
125
WatchEvent<?> ev = lastModifyEvents.get(context);
126
if (ev != null) {
127
assert ev.kind() == StandardWatchEventKinds.ENTRY_MODIFY;
128
((Event<?>)ev).increment();
129
return;
130
}
131
} else {
132
// not a modify event so remove from the map as the
133
// last event will no longer be a modify event.
134
lastModifyEvents.remove(context);
135
}
136
}
137
138
// if the list has reached the limit then drop pending events
139
// and queue an OVERFLOW event
140
if (size >= MAX_EVENT_LIST_SIZE) {
141
kind = StandardWatchEventKinds.OVERFLOW;
142
isModify = false;
143
context = null;
144
}
145
}
146
147
// non-repeated event
148
Event<Object> ev =
149
new Event<>((WatchEvent.Kind<Object>)kind, context);
150
if (isModify) {
151
lastModifyEvents.put(context, ev);
152
} else if (kind == StandardWatchEventKinds.OVERFLOW) {
153
// drop all pending events
154
events.clear();
155
lastModifyEvents.clear();
156
}
157
events.add(ev);
158
signal();
159
}
160
}
161
162
@Override
163
public final List<WatchEvent<?>> pollEvents() {
164
synchronized (this) {
165
List<WatchEvent<?>> result = events;
166
events = new ArrayList<>();
167
lastModifyEvents.clear();
168
return result;
169
}
170
}
171
172
@Override
173
public final boolean reset() {
174
synchronized (this) {
175
if (state == State.SIGNALLED && isValid()) {
176
if (events.isEmpty()) {
177
state = State.READY;
178
} else {
179
// pending events so re-queue key
180
watcher.enqueueKey(this);
181
}
182
}
183
return isValid();
184
}
185
}
186
187
/**
188
* WatchEvent implementation
189
*/
190
private static class Event<T> implements WatchEvent<T> {
191
private final WatchEvent.Kind<T> kind;
192
private final T context;
193
194
// synchronize on watch key to access/increment count
195
private int count;
196
197
Event(WatchEvent.Kind<T> type, T context) {
198
this.kind = type;
199
this.context = context;
200
this.count = 1;
201
}
202
203
@Override
204
public WatchEvent.Kind<T> kind() {
205
return kind;
206
}
207
208
@Override
209
public T context() {
210
return context;
211
}
212
213
@Override
214
public int count() {
215
return count;
216
}
217
218
// for repeated events
219
void increment() {
220
count++;
221
}
222
}
223
}
224
225