PageRenderTime 27ms CodeModel.GetById 15ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/hudson-core/src/main/java/hudson/util/CopyOnWriteMap.java

http://github.com/hudson/hudson
Java | 231 lines | 143 code | 38 blank | 50 comment | 0 complexity | 500e219558f9afec47782a9fd3588429 MD5 | raw file
  1/*
  2 * The MIT License
  3 * 
  4 * Copyright (c) 2004-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi
  5 * 
  6 * Permission is hereby granted, free of charge, to any person obtaining a copy
  7 * of this software and associated documentation files (the "Software"), to deal
  8 * in the Software without restriction, including without limitation the rights
  9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 10 * copies of the Software, and to permit persons to whom the Software is
 11 * furnished to do so, subject to the following conditions:
 12 * 
 13 * The above copyright notice and this permission notice shall be included in
 14 * all copies or substantial portions of the Software.
 15 * 
 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 22 * THE SOFTWARE.
 23 */
 24package hudson.util;
 25
 26import com.thoughtworks.xstream.converters.MarshallingContext;
 27import com.thoughtworks.xstream.converters.UnmarshallingContext;
 28import com.thoughtworks.xstream.converters.collections.MapConverter;
 29import com.thoughtworks.xstream.converters.collections.TreeMapConverter;
 30import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 31import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
 32import com.thoughtworks.xstream.mapper.Mapper;
 33
 34import java.util.Collection;
 35import java.util.Collections;
 36import java.util.Comparator;
 37import java.util.HashMap;
 38import java.util.LinkedHashMap;
 39import java.util.Map;
 40import java.util.Set;
 41import java.util.TreeMap;
 42
 43/**
 44 * {@link Map} that has copy-on-write semantics.
 45 *
 46 * <p>
 47 * This class is suitable where highly concurrent access is needed, yet
 48 * the write operation is relatively uncommon.
 49 *
 50 * @author Kohsuke Kawaguchi
 51 */
 52public abstract class CopyOnWriteMap<K,V> implements Map<K,V> {
 53    protected volatile Map<K,V> core;
 54    /**
 55     * Read-only view of {@link #core}.
 56     */
 57    private volatile Map<K,V> view;
 58
 59    protected CopyOnWriteMap(Map<K,V> core) {
 60        update(core);
 61    }
 62
 63    protected CopyOnWriteMap() {
 64        update(Collections.<K,V>emptyMap());
 65    }
 66
 67    protected void update(Map<K,V> m) {
 68        core = m;
 69        view = Collections.unmodifiableMap(core);
 70    }
 71
 72    public int size() {
 73        return core.size();
 74    }
 75
 76    public boolean isEmpty() {
 77        return core.isEmpty();
 78    }
 79
 80    public boolean containsKey(Object key) {
 81        return core.containsKey(key);
 82    }
 83
 84    public boolean containsValue(Object value) {
 85        return core.containsValue(value);
 86    }
 87
 88    public V get(Object key) {
 89        return core.get(key);
 90    }
 91
 92    public synchronized V put(K key, V value) {
 93        Map<K,V> m = copy();
 94        V r = m.put(key,value);
 95        update(m);
 96
 97        return r;
 98    }
 99
100    public synchronized V remove(Object key) {
101        Map<K,V> m = copy();
102        V r = m.remove(key);
103        update(m);
104
105        return r;
106    }
107
108    public synchronized void putAll(Map<? extends K, ? extends V> t) {
109        Map<K,V> m = copy();
110        m.putAll(t);
111        update(m);
112    }
113
114    protected abstract Map<K,V> copy();
115
116    public synchronized void clear() {
117        update(Collections.<K,V>emptyMap());
118    }
119
120    /**
121     * This method will return a read-only {@link Set}.
122     */
123    public Set<K> keySet() {
124        return view.keySet();
125    }
126
127    /**
128     * This method will return a read-only {@link Collection}.
129     */
130    public Collection<V> values() {
131        return view.values();
132    }
133
134    /**
135     * This method will return a read-only {@link Set}.
136     */
137    public Set<Entry<K,V>> entrySet() {
138        return view.entrySet();
139    }
140
141    /**
142     * {@link CopyOnWriteMap} backed by {@link HashMap}.
143     */
144    public static final class Hash<K,V> extends CopyOnWriteMap<K,V> {
145        public Hash(Map<K,V> core) {
146            super(new LinkedHashMap<K,V>(core));
147        }
148
149        public Hash() {
150        }
151
152        protected Map<K,V> copy() {
153            return new LinkedHashMap<K,V>(core);
154        }
155
156        public static class ConverterImpl extends MapConverter {
157            public ConverterImpl(Mapper mapper) {
158                super(mapper);
159            }
160
161            @Override
162            public boolean canConvert(Class type) {
163                return type==Hash.class;
164            }
165
166            @Override
167            public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
168                return new Hash((Map) super.unmarshal(reader,context));
169            }
170
171            @Override
172            public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
173                super.marshal(((Hash)source).core,writer,context);
174            }
175        }
176    }
177
178    /**
179     * {@link CopyOnWriteMap} backed by {@link TreeMap}.
180     */
181    public static final class Tree<K,V> extends CopyOnWriteMap<K,V> {
182        private final Comparator<K> comparator;
183
184        public Tree(Map<K,V> core, Comparator<K> comparator) {
185            this(comparator);
186            putAll(core);
187        }
188
189        public Tree(Comparator<K> comparator) {
190            super(new TreeMap<K,V>(comparator));
191            this.comparator = comparator;
192        }
193
194        public Tree() {
195            this(null);
196        }
197
198        protected Map<K,V> copy() {
199            TreeMap<K,V> m = new TreeMap<K,V>(comparator);
200            m.putAll(core);
201            return m;
202        }
203
204        @Override
205        public synchronized void clear() {
206            update(new TreeMap<K,V>(comparator));
207        }
208
209        public static class ConverterImpl extends TreeMapConverter {
210            public ConverterImpl(Mapper mapper) {
211                super(mapper);
212            }
213
214            @Override
215            public boolean canConvert(Class type) {
216                return type==Tree.class;
217            }
218
219            @Override
220            public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
221                TreeMap tm = (TreeMap) super.unmarshal(reader,context);
222                return new Tree(tm,tm.comparator());
223            }
224
225            @Override
226            public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
227                super.marshal(((Tree)source).core,writer,context);
228            }
229        }
230    }
231}