--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/nio/fs/AbstractWatchKey.java Sun Feb 15 12:25:54 2009 +0000
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.nio.fs;
+
+import java.nio.file.*;
+import java.util.*;
+
+/**
+ * Base implementation class for watch keys.
+ */
+
+abstract class AbstractWatchKey extends WatchKey {
+
+ /**
+ * Maximum size of event list (in the future this may be tunable)
+ */
+ static final int MAX_EVENT_LIST_SIZE = 512;
+
+ /**
+ * Special event to signal overflow
+ */
+ static final Event<Void> OVERFLOW_EVENT =
+ new Event<Void>(StandardWatchEventKind.OVERFLOW, null);
+
+ /**
+ * Possible key states
+ */
+ private static enum State { READY, SIGNALLED };
+
+ // reference to watcher
+ private final AbstractWatchService watcher;
+
+ // key state
+ private State state;
+
+ // pending events
+ private List<WatchEvent<?>> events;
+
+ protected AbstractWatchKey(AbstractWatchService watcher) {
+ this.watcher = watcher;
+ this.state = State.READY;
+ this.events = new ArrayList<WatchEvent<?>>();
+ }
+
+ final AbstractWatchService watcher() {
+ return watcher;
+ }
+
+ /**
+ * Enqueues this key to the watch service
+ */
+ final void signal() {
+ synchronized (this) {
+ if (state == State.READY) {
+ state = State.SIGNALLED;
+ watcher.enqueueKey(this);
+ }
+ }
+ }
+
+ /**
+ * Adds the event to this key and signals it.
+ */
+ @SuppressWarnings("unchecked")
+ final void signalEvent(WatchEvent.Kind<?> kind, Object context) {
+ synchronized (this) {
+ int size = events.size();
+ if (size > 1) {
+ // don't let list get too big
+ if (size >= MAX_EVENT_LIST_SIZE) {
+ kind = StandardWatchEventKind.OVERFLOW;
+ context = null;
+ }
+
+ // repeated event
+ WatchEvent<?> prev = events.get(size-1);
+ if (kind == prev.kind()) {
+ boolean isRepeat;
+ if (context == null) {
+ isRepeat = (prev.context() == null);
+ } else {
+ isRepeat = context.equals(prev.context());
+ }
+ if (isRepeat) {
+ ((Event<?>)prev).increment();
+ return;
+ }
+ }
+ }
+
+ // non-repeated event
+ events.add(new Event<Object>((WatchEvent.Kind<Object>)kind, context));
+ signal();
+ }
+ }
+
+ @Override
+ public final List<WatchEvent<?>> pollEvents() {
+ synchronized (this) {
+ List<WatchEvent<?>> result = events;
+ events = new ArrayList<WatchEvent<?>>();
+ return result;
+ }
+ }
+
+ @Override
+ public final boolean reset() {
+ synchronized (this) {
+ if (state == State.SIGNALLED && isValid()) {
+ if (events.isEmpty()) {
+ state = State.READY;
+ } else {
+ // pending events so re-queue key
+ watcher.enqueueKey(this);
+ }
+ }
+ return isValid();
+ }
+ }
+
+ /**
+ * WatchEvent implementation
+ */
+ private static class Event<T> extends WatchEvent<T> {
+ private final WatchEvent.Kind<T> kind;
+ private final T context;
+
+ // synchronize on watch key to access/increment count
+ private int count;
+
+ Event(WatchEvent.Kind<T> type, T context) {
+ this.kind = type;
+ this.context = context;
+ this.count = 1;
+ }
+
+ @Override
+ public WatchEvent.Kind<T> kind() {
+ return kind;
+ }
+
+ @Override
+ public T context() {
+ return context;
+ }
+
+ @Override
+ public int count() {
+ return count;
+ }
+
+ // for repeated events
+ void increment() {
+ count++;
+ }
+ }
+}