History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/nio/fs/AbstractWatchKey.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/nio/fs/AbstractWatchKey.java+223−0
@@ -0,0 +1,223 @@
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
26package sun.nio.fs;
27
28import java.nio.file.*;
29import java.util.*;
30
31/**
32 * Base implementation class for watch keys.
33 */
34
35abstract 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<WatchEvent<?>>();
74 this.lastModifyEvents = new HashMap<Object,WatchEvent<?>>();
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<Object>((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<WatchEvent<?>>();
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}