/*
* 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.
*
* Contributions from 2013-2017 where performed either by US government
* employees, or under US Veterans Health Administration contracts.
*
* US Veterans Health Administration contributions by government employees
* are work of the U.S. Government and are not subject to copyright
* protection in the United States. Portions contributed by government
* employees are USGovWork (17USC ยง105). Not subject to copyright.
*
* Contribution by contractors to the US Veterans Health Administration
* during this period are contractually contributed under the
* Apache License, Version 2.0.
*
* See: https://www.usa.gov/government-works
*
* Contributions prior to 2013:
*
* Copyright (C) International Health Terminology Standards Development Organisation.
* Licensed under the Apache License, Version 2.0.
*
*/
package sh.isaac.api.collections.uuidnidmap;
//~--- JDK imports ------------------------------------------------------------
import java.util.UUID;
import java.util.concurrent.locks.StampedLock;
//~--- classes ----------------------------------------------------------------
/**
* Created by kec on 7/25/14.
*/
public class ConcurrentUuidToIntHashMap
extends UuidToIntHashMap {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -6525403154660005459L;
//~--- fields --------------------------------------------------------------
/** The sl. */
StampedLock sl = new StampedLock();
//~--- constructors --------------------------------------------------------
/**
* Constructs an empty map with default capacity and default load factors.
*/
public ConcurrentUuidToIntHashMap() {
super(defaultCapacity);
}
/**
* Constructs an empty map with the specified initial capacity and default load factors.
*
* @param initialCapacity the initial capacity of the map.
* @throws IllegalArgumentException if the initial capacity is less than zero.
*/
public ConcurrentUuidToIntHashMap(int initialCapacity) {
super(initialCapacity, defaultMinLoadFactor, defaultMaxLoadFactor);
}
/**
* Constructs an empty map with the specified initial capacity and the specified minimum and maximum load
* factor.
*
* @param initialCapacity the initial capacity.
* @param minLoadFactor the minimum load factor.
* @param maxLoadFactor the maximum load factor.
* @throws IllegalArgumentException if
*
* {@code initialCapacity < 0 || (minLoadFactor < 0.0 || minLoadFactor >= 1.0) || (maxLoadFactor <= 0.0 ||
* maxLoadFactor >= 1.0) || (minLoadFactor >= maxLoadFactor)} .
*/
public ConcurrentUuidToIntHashMap(int initialCapacity, double minLoadFactor, double maxLoadFactor) {
super(initialCapacity, minLoadFactor, maxLoadFactor);
}
//~--- methods -------------------------------------------------------------
/**
* Contains key.
*
* @param key the key
* @return true, if successful
*/
@Override
public boolean containsKey(long[] key) {
long stamp = this.sl.tryOptimisticRead();
boolean containsKey = indexOfKey(key) >= 0;
if (!this.sl.validate(stamp)) {
stamp = this.sl.readLock();
try {
containsKey = indexOfKey(key) >= 0;
} finally {
this.sl.unlockRead(stamp);
}
}
return containsKey;
}
/**
* Contains key.
*
* @param key the key
* @return true, if successful
*/
@Override
public boolean containsKey(UUID key) {
return this.containsKey(new long[] { key.getMostSignificantBits(), key.getLeastSignificantBits() });
}
/**
* Put.
*
* @param key the key
* @param value the value
* @return true, if successful
*/
@Override
public boolean put(long[] key, int value) {
throw new UnsupportedOperationException("Use put(long[] key, int value, long stamp) instead.");
}
/**
* Put.
*
* @param key the key
* @param value the value
* @param stamp the stamp
* @return true, if successful
*/
public boolean put(long[] key, int value, long stamp) {
this.sl.validate(stamp);
return super.put(key, value);
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the distinct.
*
* @return the distinct
*/
public int getDistinct() {
return this.distinct;
}
//~--- set methods ---------------------------------------------------------
/**
* Sets the distinct.
*
* @param distinct the new distinct
*/
public void setDistinct(int distinct) {
this.distinct = distinct;
}
//~--- get methods ---------------------------------------------------------
/**
* Gets the.
*
* @param key the key
* @return the int
*/
@Override
public int get(long[] key) {
long stamp = this.sl.tryOptimisticRead();
int value = super.get(key);
if (!this.sl.validate(stamp)) {
stamp = this.sl.readLock();
try {
value = super.get(key);
} finally {
this.sl.unlockRead(stamp);
}
}
return value;
}
/**
* Gets the.
*
* @param key the key
* @return the int
*/
@Override
public int get(UUID key) {
return this.get(new long[] { key.getMostSignificantBits(), key.getLeastSignificantBits() });
}
/**
* Gets the.
*
* @param key the key
* @param stampLong the stamp long
* @return the int
*/
public int get(long[] key, long stampLong) {
return super.get(key);
}
/**
* Gets the.
*
* @param key the key
* @param stampSequence the stamp sequence
* @return the int
*/
public int get(UUID key, long stampSequence) {
return this.get(new long[] { key.getMostSignificantBits(), key.getLeastSignificantBits() }, stampSequence);
}
/**
* Gets the stamped lock.
*
* @return the stamped lock
*/
public StampedLock getStampedLock() {
return this.sl;
}
/**
* Gets the stats.
*
* @return the stats
*/
public String getStats() {
return "distinct: " + getDistinct() + " free: " + getFreeEntries() + " utilization: " +
getDistinct() * 100 / (getDistinct() + getFreeEntries());
}
}