All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bson.util.CopyOnWriteMap Maven / Gradle / Ivy

There is a newer version: 5.10
Show newest version
/**
 * Copyright 2008 Atlassian Pty Ltd 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package org.bson.util;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.WeakHashMap;

import org.bson.util.annotations.GuardedBy;
import org.bson.util.annotations.ThreadSafe;

import org.bson.util.AbstractCopyOnWriteMap.View.Type;

/**
 * A thread-safe variant of {@link Map} in which all mutative operations (the
 * "destructive" operations described by {@link Map} put, remove and so on) are
 * implemented by making a fresh copy of the underlying map.
 * 

* This is ordinarily too costly, but may be more efficient than * alternatives when traversal operations vastly out-number mutations, and is * useful when you cannot or don't want to synchronize traversals, yet need to * preclude interference among concurrent threads. The "snapshot" style * iterators on the collections returned by {@link #entrySet()}, * {@link #keySet()} and {@link #values()} use a reference to the internal map * at the point that the iterator was created. This map never changes during the * lifetime of the iterator, so interference is impossible and the iterator is * guaranteed not to throw ConcurrentModificationException. The * iterators will not reflect additions, removals, or changes to the list since * the iterator was created. Removing elements via these iterators is not * supported. The mutable operations on these collections (remove, retain etc.) * are supported but as with the {@link Map} interface, add and addAll are not * and throw {@link UnsupportedOperationException}. *

* The actual copy is performed by an abstract {@link #copy(Map)} method. The * method is responsible for the underlying Map implementation (for instance a * {@link HashMap}, {@link TreeMap}, {@link LinkedHashMap} etc.) and therefore * the semantics of what this map will cope with as far as null keys and values, * iteration ordering etc. See the note below about suitable candidates for * underlying Map implementations *

* There are supplied implementations for the common j.u.c {@link Map} * implementations via the {@link CopyOnWriteMap} static {@link Builder}. *

* Collection views of the keys, values and entries are optionally * {@link View.Type.LIVE live} or {@link View.Type.STABLE stable}. Live views * are modifiable will cause a copy if a modifying method is called on them. * Methods on these will reflect the current state of the collection, although * iterators will be snapshot style. If the collection views are stable they are * unmodifiable, and will be a snapshot of the state of the map at the time the * collection was asked for. *

* Please note that the thread-safety guarantees are limited to * the thread-safety of the non-mutative (non-destructive) operations of the * underlying map implementation. For instance some implementations such as * {@link WeakHashMap} and {@link LinkedHashMap} with access ordering are * actually structurally modified by the {@link #get(Object)} method and are * therefore not suitable candidates as delegates for this class. * * @param the key type * @param the value type * @author Jed Wesley-Smith */ @ThreadSafe abstract class CopyOnWriteMap extends AbstractCopyOnWriteMap> { private static final long serialVersionUID = 7935514534647505917L; /** * Get a {@link Builder} for a {@link CopyOnWriteMap} instance. * * @param key type * @param value type * @return a fresh builder */ public static Builder builder() { return new Builder(); } /** * Build a {@link CopyOnWriteMap} and specify all the options. * * @param key type * @param value type */ public static class Builder { private View.Type viewType = View.Type.STABLE; private final Map initialValues = new HashMap(); Builder() {} /** * Views are stable (fixed in time) and unmodifiable. */ public Builder stableViews() { viewType = View.Type.STABLE; return this; } /** * Views are live (reflecting concurrent updates) and mutator methods * are supported. */ public Builder addAll(final Map values) { initialValues.putAll(values); return this; } /** * Views are live (reflecting concurrent updates) and mutator methods * are supported. */ public Builder liveViews() { viewType = View.Type.LIVE; return this; } public CopyOnWriteMap newHashMap() { return new Hash(initialValues, viewType); } public CopyOnWriteMap newLinkedMap() { return new Linked(initialValues, viewType); } } /** * Creates a new {@link CopyOnWriteMap} with an underlying {@link HashMap}. *

* This map has {@link View.Type.STABLE stable} views. */ public static CopyOnWriteMap newHashMap() { final Builder builder = builder(); return builder.newHashMap(); } /** * Creates a new {@link CopyOnWriteMap} with an underlying {@link HashMap} * using the supplied map as the initial values. *

* This map has {@link View.Type.STABLE stable} views. */ public static CopyOnWriteMap newHashMap(final Map map) { final Builder builder = builder(); return builder.addAll(map).newHashMap(); } /** * Creates a new {@link CopyOnWriteMap} with an underlying * {@link LinkedHashMap}. Iterators for this map will be return elements in * insertion order. *

* This map has {@link View.Type.STABLE stable} views. */ public static CopyOnWriteMap newLinkedMap() { final Builder builder = builder(); return builder.newLinkedMap(); } /** * Creates a new {@link CopyOnWriteMap} with an underlying * {@link LinkedHashMap} using the supplied map as the initial values. * Iterators for this map will be return elements in insertion order. *

* This map has {@link View.Type.STABLE stable} views. */ public static CopyOnWriteMap newLinkedMap(final Map map) { final Builder builder = builder(); return builder.addAll(map).newLinkedMap(); } // // constructors // /** * Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to * initialize the values. * * @param map the initial map to initialize with * @deprecated since 0.0.12 use the versions that explicitly specify * View.Type */ @Deprecated protected CopyOnWriteMap(final Map map) { this(map, View.Type.LIVE); } /** * Create a new empty {@link CopyOnWriteMap}. * * @deprecated since 0.0.12 use the versions that explicitly specify * View.Type */ @Deprecated protected CopyOnWriteMap() { this(Collections. emptyMap(), View.Type.LIVE); } /** * Create a new {@link CopyOnWriteMap} with the supplied {@link Map} to * initialize the values. This map may be optionally modified using any of * the key, entry or value views * * @param map the initial map to initialize with */ protected CopyOnWriteMap(final Map map, final View.Type viewType) { super(map, viewType); } /** * Create a new empty {@link CopyOnWriteMap}. This map may be optionally * modified using any of the key, entry or value views */ protected CopyOnWriteMap(final View.Type viewType) { super(Collections. emptyMap(), viewType); } @Override @GuardedBy("internal-lock") protected abstract > Map copy(N map); // // inner classes // /** * Uses {@link HashMap} instances as its internal storage. */ static class Hash extends CopyOnWriteMap { private static final long serialVersionUID = 5221824943734164497L; Hash(final Map map, final Type viewType) { super(map, viewType); } @Override public > Map copy(final N map) { return new HashMap(map); } } /** * Uses {@link LinkedHashMap} instances as its internal storage. */ static class Linked extends CopyOnWriteMap { private static final long serialVersionUID = -8659999465009072124L; Linked(final Map map, final Type viewType) { super(map, viewType); } @Override public > Map copy(final N map) { return new LinkedHashMap(map); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy