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

io.atlassian.util.concurrent.CopyOnWriteMap Maven / Gradle / Ivy

Go to download

This project contains utility classes that are used by various products and projects inside Atlassian and may have some utility to the world at large.

The 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 io.atlassian.util.concurrent;

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

import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.ThreadSafe;

import io.atlassian.util.concurrent.AbstractCopyOnWriteMap.View.Type;

/**
 * A thread-safe variant of {@link java.util.Map} in which all mutative
 * operations (the "destructive" operations described by {@link java.util.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 java.util.Map} interface, add and addAll * are not and throw {@link java.lang.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 java.util.HashMap}, {@link java.util.TreeMap}, * {@link java.util.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 java.util.Map} * implementations via the {@link io.atlassian.util.concurrent.CopyOnWriteMap} * static {@link io.atlassian.util.concurrent.CopyOnWriteMap.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 java.util.WeakHashMap} and {@link java.util.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 public abstract class CopyOnWriteMap extends AbstractCopyOnWriteMap> { private static final long serialVersionUID = 7935514534647505917L; /** * Get a {@link io.atlassian.util.concurrent.CopyOnWriteMap.Builder} for a * {@link io.atlassian.util.concurrent.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 io.atlassian.util.concurrent.CopyOnWriteMap} with an * underlying {@link java.util.HashMap}. *

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

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

* This map has {@link View.Type#STABLE stable} views. * * @return a {@link io.atlassian.util.concurrent.CopyOnWriteMap}. */ public static CopyOnWriteMap newLinkedMap() { final Builder builder = builder(); return builder.newLinkedMap(); } /** * Creates a new {@link io.atlassian.util.concurrent.CopyOnWriteMap} with an * underlying {@link java.util.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. * * @param map a {@link java.util.Map} object. * @return a {@link io.atlassian.util.concurrent.CopyOnWriteMap}. */ public static CopyOnWriteMap newLinkedMap(final Map map) { final Builder builder = builder(); return builder.addAll(map).newLinkedMap(); } // // constructors // /** * Create a new {@link io.atlassian.util.concurrent.CopyOnWriteMap} with the * supplied {@link java.util.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 io.atlassian.util.concurrent.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 io.atlassian.util.concurrent.CopyOnWriteMap} with the * supplied {@link java.util.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 * @param viewType a View.Type. */ protected CopyOnWriteMap(final Map map, final View.Type viewType) { super(map, viewType); } /** * Create a new empty {@link io.atlassian.util.concurrent.CopyOnWriteMap}. * This map may be optionally modified using any of the key, entry or value * views * * @param viewType a View.Type. */ protected CopyOnWriteMap(final View.Type viewType) { super(Collections. emptyMap(), viewType); } /** {@inheritDoc} */ @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 final > 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 final > Map copy(final N map) { return new LinkedHashMap(map); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy