/*******************************************************************************
* Copyright 2013 Analog Devices, Inc.
*
* 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 com.analog.lyric.collect;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentSkipListMap;
import net.jcip.annotations.ThreadSafe;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
/**
* An extension of {@link CopyOnWriteMap} for delegating to a {@link ConcurrentMap}.
*/
@ThreadSafe
@NonNullByDefault(false)
public class CopyOnWriteConcurrentMap<K, V> extends CopyOnWriteMap<K,V> implements ConcurrentMap<K,V>
{
/*--------------
* Construction
*/
/**
* Construct map delegating to {@code underlyingMap} until
* the first mutating operation, which will trigger a copy
* to be made.
*/
public CopyOnWriteConcurrentMap(@NonNull ConcurrentMap<K,V> underlyingMap)
{
super(underlyingMap);
}
/*-----------------------
* ConcurrentMap methods
*/
/**
* {@link #wasCopied()} will be true after invoking this.
*/
@Override
public V putIfAbsent(K key, V value)
{
return mutableMap().putIfAbsent(key, value);
}
/**
* {@link #wasCopied()} will be true after invoking this.
*/
@Override
public boolean remove(Object key, Object value)
{
return mutableMap().remove(key, value);
}
/**
* {@link #wasCopied()} will be true after invoking this.
*/
@Override
public @Nullable V replace(K key, V value)
{
return mutableMap().replace(key, value);
}
/**
* {@link #wasCopied()} will be true after invoking this.
*/
@Override
public boolean replace(K key, V oldValue, V newValue)
{
return mutableMap().replace(key, oldValue, newValue);
}
/*----------------------------------
* CopyOnWriteConcurrentMap methods
*/
@Override
public @NonNull ConcurrentMap<K,V> originalMap()
{
return (ConcurrentMap<K, V>)super.originalMap();
}
@Override
protected @NonNull ConcurrentMap<K,V> copyOriginalMap()
{
return (ConcurrentMap<K, V>) super.copyOriginalMap();
}
/**
* Creates an empty map with specified initial capacity.
* <p>
* This implementation returns a new {@link ConcurrentSkipListMap} if the
* {@link #originalMap()} is a {@link SortedMap} and otherwise returns
* a new {@link ConcurrentHashMap}.
* <p>
* Subclasses may override this method to return other map types.
*/
@Override
protected @NonNull ConcurrentMap<K,V> createEmptyMap(int capacity)
{
Map<K,V> original = originalMap();
if (original instanceof SortedMap)
{
return new ConcurrentSkipListMap<K, V>(((SortedMap<K,V>)original).comparator());
}
else
{
return new ConcurrentHashMap<K,V>(original.size());
}
}
/*-----------------
* Private methods
*/
@Override
protected @NonNull ConcurrentMap<K,V> readOnlyMap()
{
return (ConcurrentMap<K, V>) super.readOnlyMap();
}
@Override
protected @NonNull ConcurrentMap<K,V> mutableMap()
{
return (ConcurrentMap<K, V>) super.mutableMap();
}
}