001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.util;
021:
022: import java.util.Collection;
023: import java.util.HashMap;
024: import java.util.Map;
025: import java.util.Set;
026:
027: /**
028: * A thread-safe version of {@link Map} in which all operations that change the
029: * Map are implemented by making a new copy of the underlying Map.
030: *
031: * While the creation of a new Map can be expensive, this class is designed for
032: * cases in which the primary function is to read data from the Map, not to
033: * modify the Map. Therefore the operations that do not cause a change to this
034: * class happen quickly and concurrently.
035: *
036: * @author The Apache MINA Project (dev@mina.apache.org)
037: * @version $Rev$, $Date$
038: */
039: public class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable {
040: private volatile Map<K, V> internalMap;
041:
042: /**
043: * Creates a new instance of CopyOnWriteMap.
044: *
045: */
046: public CopyOnWriteMap() {
047: internalMap = new HashMap<K, V>();
048: }
049:
050: /**
051: * Creates a new instance of CopyOnWriteMap with the specified initial size
052: *
053: * @param initialCapacity
054: * The initial size of the Map.
055: */
056: public CopyOnWriteMap(int initialCapacity) {
057: internalMap = new HashMap<K, V>(initialCapacity);
058: }
059:
060: /**
061: * Creates a new instance of CopyOnWriteMap in which the
062: * initial data being held by this map is contained in
063: * the supplied map.
064: *
065: * @param data
066: * A Map containing the initial contents to be placed into
067: * this class.
068: */
069: public CopyOnWriteMap(Map<K, V> data) {
070: internalMap = new HashMap<K, V>(data);
071: }
072:
073: /**
074: * Adds the provided key and value to this map.
075: *
076: * @see java.util.Map#put(java.lang.Object, java.lang.Object)
077: */
078: public V put(K key, V value) {
079: synchronized (this ) {
080: Map<K, V> newMap = new HashMap<K, V>(internalMap);
081: V val = newMap.put(key, value);
082: internalMap = newMap;
083: return val;
084: }
085: }
086:
087: /**
088: * Removed the value and key from this map based on the
089: * provided key.
090: *
091: * @see java.util.Map#remove(java.lang.Object)
092: */
093: public V remove(Object key) {
094: synchronized (this ) {
095: Map<K, V> newMap = new HashMap<K, V>(internalMap);
096: V val = newMap.remove(key);
097: internalMap = newMap;
098: return val;
099: }
100: }
101:
102: /**
103: * Inserts all the keys and values contained in the
104: * provided map to this map.
105: *
106: * @see java.util.Map#putAll(java.util.Map)
107: */
108: public void putAll(Map<? extends K, ? extends V> newData) {
109: synchronized (this ) {
110: Map<K, V> newMap = new HashMap<K, V>(internalMap);
111: newMap.putAll(newData);
112: internalMap = newMap;
113: }
114: }
115:
116: /**
117: * Removes all entries in this map.
118: *
119: * @see java.util.Map#clear()
120: */
121: public void clear() {
122: synchronized (this ) {
123: internalMap = new HashMap<K, V>();
124: }
125: }
126:
127: // ==============================================
128: // ==== Below are methods that do not modify ====
129: // ==== the internal Maps ====
130: // ==============================================
131: /**
132: * Returns the number of key/value pairs in this map.
133: *
134: * @see java.util.Map#size()
135: */
136: public int size() {
137: return internalMap.size();
138: }
139:
140: /**
141: * Returns true if this map is empty, otherwise false.
142: *
143: * @see java.util.Map#isEmpty()
144: */
145: public boolean isEmpty() {
146: return internalMap.isEmpty();
147: }
148:
149: /**
150: * Returns true if this map contains the provided key, otherwise
151: * this method return false.
152: *
153: * @see java.util.Map#containsKey(java.lang.Object)
154: */
155: public boolean containsKey(Object key) {
156: return internalMap.containsKey(key);
157: }
158:
159: /**
160: * Returns true if this map contains the provided value, otherwise
161: * this method returns false.
162: *
163: * @see java.util.Map#containsValue(java.lang.Object)
164: */
165: public boolean containsValue(Object value) {
166: return internalMap.containsValue(value);
167: }
168:
169: /**
170: * Returns the value associated with the provided key from this
171: * map.
172: *
173: * @see java.util.Map#get(java.lang.Object)
174: */
175: public V get(Object key) {
176: return internalMap.get(key);
177: }
178:
179: /**
180: * This method will return a read-only {@link Set}.
181: */
182: public Set<K> keySet() {
183: return internalMap.keySet();
184: }
185:
186: /**
187: * This method will return a read-only {@link Collection}.
188: */
189: public Collection<V> values() {
190: return internalMap.values();
191: }
192:
193: /**
194: * This method will return a read-only {@link Set}.
195: */
196: public Set<Entry<K, V>> entrySet() {
197: return internalMap.entrySet();
198: }
199:
200: @Override
201: public Object clone() {
202: try {
203: return super .clone();
204: } catch (CloneNotSupportedException e) {
205: throw new InternalError();
206: }
207: }
208: }
|