org.chromium.sdk/src/org/chromium/sdk/internal/CloseableMap.java
changeset 2 e4420d2515f1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.sdk/src/org/chromium/sdk/internal/CloseableMap.java	Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,79 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.sdk.internal;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Utility class that behaves similarly to ConcurrentHashMap, but also
+ * provides {@link #close} operation that stops all new registrations.
+ */
+public class CloseableMap<K, V> {
+  public static <K, V> CloseableMap<K, V> newMap() {
+    return new CloseableMap<K, V>(new ConcurrentHashMap<K, V>());
+  }
+
+  public static <K, V> CloseableMap<K, V> newLinkedMap() {
+    // Creates linked hash map and makes "get" synchronized.
+    return new CloseableMap<K, V>(new LinkedHashMap<K, V>()) {
+      @Override
+      public synchronized V get(K key) {
+        // Base "get" is not synchronized, because we rely on ConcurrentHashMap.
+        return super.get(key);
+      }
+    };
+  }
+
+  private final Map<K, V> map;
+  private boolean mutationClosed = false;
+
+  protected CloseableMap(Map<K, V> map) {
+    this.map = map;
+  }
+
+  public V get(K key) {
+    return map.get(key);
+  }
+
+  public synchronized Map<K, V> close() {
+    if (mutationClosed) {
+      throw new IllegalStateException();
+    }
+    mutationClosed = true;
+    return map;
+  }
+
+  public synchronized V remove(K key) {
+    if (mutationClosed) {
+      // We probably can safely ignore this.
+      return null;
+    }
+    V result = map.remove(key);
+    if (result == null) {
+      throw new IllegalArgumentException("This key is not registered");
+    }
+    return result;
+  }
+
+  public synchronized V removeIfContains(K key) {
+    if (mutationClosed) {
+      // We probably can safely ignore this.
+      return null;
+    }
+    return map.remove(key);
+  }
+
+  public synchronized void put(K key, V value) {
+    if (mutationClosed) {
+      throw new IllegalStateException();
+    }
+    if (map.containsKey(key)) {
+      throw new IllegalStateException("Such key is already registered");
+    }
+    map.put(key, value);
+  }
+}