() {
* public boolean equal(Person k, Object x) {
- * return x instanceOf Person && k.name.equals(((Person)x).name);
+ * return x instanceof Person && k.name.equals(((Person)x).name);
* }
* public int hash(Object x) {
- * return (x instanceOf Person)? ((Person)x).name.hashCode() : 0;
+ * return (x instanceof Person) ? ((Person)x).name.hashCode() : 0;
* }
* },
* STRONG, EQUALS, 0);
@@ -72,24 +72,24 @@ import sun.misc.Unsafe;
*
* This class also includes nested class {@link KeySet}
* that provides space-efficient Set views of maps, also supporting
- * method intern
, which may be of use in canonicalizing
+ * method {@code intern}, which may be of use in canonicalizing
* elements.
*
*
When used with (Weak or Soft) Reference keys and/or values,
- * elements that have asynchronously become null
are
+ * elements that have asynchronously become {@code null} are
* treated as absent from the map and (eventually) removed from maps
* via a background thread common across all maps. Because of the
* potential for asynchronous clearing of References, methods such as
- * containsValue
have weaker guarantees than you might
+ * {@code containsValue} have weaker guarantees than you might
* expect even in the absence of other explicitly concurrent
- * operations. For example containsValue(value)
may
- * return true even if value
is no longer available upon
+ * operations. For example {@code containsValue(value)} may
+ * return true even if {@code value} is no longer available upon
* return from the method.
*
*
When Equivalences other than equality are used, the returned
- * collections may violate the specifications of Map and/or
- * Set interfaces, which mandate the use of the
- * equals method when comparing objects. The methods of this
+ * collections may violate the specifications of {@code Map} and/or
+ * {@code Set} interfaces, which mandate the use of the
+ * {@code equals} method when comparing objects. The methods of this
* class otherwise have properties similar to those of {@link
* java.util.ConcurrentHashMap} under its default settings. To
* adaptively maintain semantics and performance under varying
@@ -165,8 +165,8 @@ public class CustomConcurrentHashMapK may be
- * entered into a Map, any Object
may be tested for
+ * java.util.Map}: While only elements of {@code K} may be
+ * entered into a Map, any {@code Object} may be tested for
* membership. Note that the performance of hash maps is heavily
* dependent on the quality of hash functions.
*/
@@ -224,7 +224,7 @@ public class CustomConcurrentHashMapnull if there is no mapping.
+ * or {@code null} if there is no mapping.
*/
public static interface MappingFunction {
/**
@@ -236,7 +236,7 @@ public class CustomConcurrentHashMapnull if there is
+ * current value to a new value, or {@code null} if there is
* no mapping
*/
public static interface RemappingFunction {
@@ -320,7 +320,7 @@ public class CustomConcurrentHashMap= MAX_SEGMENT_CAPACITY)
return oldTable;
- Node[] newTable =
- (Node[])new Node[oldCapacity<<1];
+ Node[] newTable = new Node[oldCapacity<<1];
int sizeMask = newTable.length - 1;
NodeFactory fac = cchm.factory;
for (int i = 0; i < oldCapacity ; i++) {
@@ -537,14 +535,14 @@ public class CustomConcurrentHashMap MAX_SEGMENT_CAPACITY)
- capacity = MAX_SEGMENT_CAPACITY;
+ capacity = MAX_SEGMENT_CAPACITY;
this.initialSegmentCapacity = capacity;
}
- this.segments = (Segment[])new Segment[NSEGMENTS];
+ this.segments = new Segment[NSEGMENTS];
}
/**
- * Creates a new CustomConcurrentHashMap with the given parameters
+ * Creates a new CustomConcurrentHashMap with the given parameters.
* @param keyStrength the strength for keys
* @param keyEquivalence the Equivalence to use for keys
* @param valueStrength the strength for values
@@ -573,7 +571,7 @@ public class CustomConcurrentHashMap>> SEGMENT_SHIFT) & SEGMENT_MASK;
Segment seg = segs[index];
if (seg == null) {
- synchronized(segs) {
+ synchronized (segs) {
seg = segs[index];
if (seg == null) {
seg = new Segment();
@@ -656,7 +654,7 @@ public class CustomConcurrentHashMaptrue if this map contains a key equivalent to
+ * Returns {@code true} if this map contains a key equivalent to
* the given key with respect to this map's key Equivalence.
*
* @param key possible key
- * @return true if this map contains the specified key
+ * @return {@code true} if this map contains the specified key
* @throws NullPointerException if the specified key is null
*/
public boolean containsKey(Object key) {
@@ -697,10 +695,10 @@ public class CustomConcurrentHashMapnull if
+ * @return the value associated with the key or {@code null} if
* there is no mapping.
* @throws NullPointerException if the specified key is null
*/
@@ -752,8 +750,8 @@ public class CustomConcurrentHashMapkey, or
- * null if there was no mapping for key
+ * @return the previous value associated with {@code key}, or
+ * {@code null} if there was no mapping for {@code key}
* @throws NullPointerException if the specified key or value is null
*/
public V put(K key, V value) {
@@ -764,7 +762,7 @@ public class CustomConcurrentHashMapnull if there was no mapping for the key
+ * or {@code null} if there was no mapping for the key
* @throws NullPointerException if the specified key or value is null
*/
public V putIfAbsent(K key, V value) {
@@ -813,7 +811,7 @@ public class CustomConcurrentHashMapnull if there was no mapping for the key
+ * or {@code null} if there was no mapping for the key
* @throws NullPointerException if the specified key or value is null
*/
public boolean replace(K key, V oldValue, V newValue) {
@@ -845,8 +843,8 @@ public class CustomConcurrentHashMapkey, or
- * null if there was no mapping for key
+ * @return the previous value associated with {@code key}, or
+ * {@code null} if there was no mapping for {@code key}
* @throws NullPointerException if the specified key is null
*/
public V remove(Object key) {
@@ -942,7 +940,7 @@ public class CustomConcurrentHashMaptrue if this map contains no key-value mappings.
+ * Returns {@code true} if this map contains no key-value mappings.
*
- * @return true if this map contains no key-value mappings
+ * @return {@code true} if this map contains no key-value mappings
*/
public final boolean isEmpty() {
final Segment[] segs = this.segments;
@@ -997,8 +995,8 @@ public class CustomConcurrentHashMapInteger.MAX_VALUE elements, returns
- * Integer.MAX_VALUE.
+ * map contains more than {@code Integer.MAX_VALUE} elements, returns
+ * {@code Integer.MAX_VALUE}.
*
* @return the number of key-value mappings in this map
*/
@@ -1010,18 +1008,18 @@ public class CustomConcurrentHashMap= Integer.MAX_VALUE? Integer.MAX_VALUE : (int)sum;
+ return (sum >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) sum;
}
/**
- * Returns true if this map maps one or more keys to a
+ * Returns {@code true} if this map maps one or more keys to a
* value equivalent to the given value with respect to this map's
* value Equivalence. Note: This method requires a full internal
* traversal of the hash table, and so is much slower than method
- * containsKey.
+ * {@code containsKey}.
*
* @param value value whose presence in this map is to be tested
- * @return true if this map maps one or more keys to the
+ * @return {@code true} if this map maps one or more keys to the
* specified value
* @throws NullPointerException if the specified value is null
*/
@@ -1069,7 +1067,7 @@ public class CustomConcurrentHashMap
* if (map.containsKey(key))
@@ -1091,8 +1089,8 @@ public class CustomConcurrentHashMapnull if the computation
- * returned null.
+ * the specified key, or {@code null} if the computation
+ * returned {@code null}.
* @throws NullPointerException if the specified key or mappingFunction
* is null,
* @throws RuntimeException or Error if the mappingFunction does so,
@@ -1158,14 +1156,14 @@ public class CustomConcurrentHashMap
* map.compute(word, new RemappingFunction<String,Integer>() {
* public Integer remap(String k, Integer v) {
- * return v == null? 1 : v + 1;
+ * return (v == null) ? 1 : v + 1;
* }});
*
*
* @param key key with which the specified value is to be associated
* @param remappingFunction the function to compute a value
* @return the updated value or
- * null if the computation returned null
+ * {@code null} if the computation returned {@code null}
* @throws NullPointerException if the specified key or remappingFunction
* is null,
* @throws RuntimeException or Error if the remappingFunction does so,
@@ -1414,7 +1412,8 @@ public class CustomConcurrentHashMap e = (Map.Entry,?>)o;
- return CustomConcurrentHashMap.this.remove(e.getKey(), e.getValue());
+ return CustomConcurrentHashMap.this.remove(e.getKey(),
+ e.getValue());
}
public int size() {
return CustomConcurrentHashMap.this.size();
@@ -1432,12 +1431,12 @@ public class CustomConcurrentHashMapIterator.remove, Set.remove,
- * removeAll, retainAll, and clear
- * operations. It does not support the add or
- * addAll operations.
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or
+ * {@code addAll} operations.
*
- * The view's iterator is a "weakly consistent" iterator
+ *
The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1453,12 +1452,12 @@ public class CustomConcurrentHashMapIterator.remove,
- * Collection.remove, removeAll,
- * retainAll, and clear operations. It does not
- * support the add or addAll operations.
+ * mapping from this map, via the {@code Iterator.remove},
+ * {@code Collection.remove}, {@code removeAll},
+ * {@code retainAll}, and {@code clear} operations. It does not
+ * support the {@code add} or {@code addAll} operations.
*
- * The view's iterator is a "weakly consistent" iterator
+ *
The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1474,12 +1473,12 @@ public class CustomConcurrentHashMapIterator.remove, Set.remove,
- * removeAll, retainAll, and clear
- * operations. It does not support the add or
- * addAll operations.
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll}, and {@code clear}
+ * operations. It does not support the {@code add} or
+ * {@code addAll} operations.
*
- * The view's iterator is a "weakly consistent" iterator
+ *
The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1494,13 +1493,13 @@ public class CustomConcurrentHashMaptrue if the given object is also a map of the
+ * Returns {@code true} if the given object is also a map of the
* same size, holding keys that are equal using this Map's key
* Equivalence, and which map to values that are equal according
* to this Map's value equivalence.
*
* @param o object to be compared for equality with this map
- * @return true if the specified object is equal to this map
+ * @return {@code true} if the specified object is equal to this map
*/
public boolean equals(Object o) {
if (o == this)
@@ -1537,7 +1536,7 @@ public class CustomConcurrentHashMapentrySet() view, which in turn are the hash codes
+ * {@code entrySet()} view, which in turn are the hash codes
* computed using key and value Equivalences for this Map.
* @return the hash code
*/
@@ -1550,15 +1549,15 @@ public class CustomConcurrentHashMap e : entrySet()) {
s.writeObject(e.getKey());
@@ -1569,13 +1568,13 @@ public class CustomConcurrentHashMapCollections.newSetFromMap applied to a
- * CustomConcurrentHashMap
, but possibly more
+ * {@code Collections.newSetFromMap} applied to a
+ * {@code CustomConcurrentHashMap}, but possibly more
* space-efficient. The set does not permit null elements. The
* set is serializable; however, serializing a set that uses soft
* or weak references can give unpredictable results.
@@ -1599,7 +1598,7 @@ public class CustomConcurrentHashMap cchm;
/**
- * Creates a set with the given parameters
+ * Creates a set with the given parameters.
* @param strength the strength of elements
* @param equivalence the Equivalence to use
* @param expectedSize an estimate of the number of elements
@@ -1620,7 +1619,7 @@ public class CustomConcurrentHashMaptrue if this set contains an
+ * Returns {@code true} if this set contains an
* element equivalent to the given element with respect
* to this set's Equivalence.
* @param o element whose presence in this set is to be tested
- * @return true if this set contains the specified element
+ * @return {@code true} if this set contains the specified element
*/
public boolean contains(Object o) {
return cchm.containsKey(o);
@@ -1655,7 +1654,7 @@ public class CustomConcurrentHashMaptrue if this set did not already contain
+ * @return {@code true} if this set did not already contain
* the specified element
*/
public boolean add(K e) {
@@ -1667,16 +1666,16 @@ public class CustomConcurrentHashMaptrue if the set contained the specified element
+ * @return {@code true} if the set contained the specified element
*/
public boolean remove(Object o) {
return cchm.remove(o) != null;
}
/**
- * Returns true if this set contains no elements.
+ * Returns {@code true} if this set contains no elements.
*
- * @return true if this set contains no elements
+ * @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return cchm.isEmpty();
@@ -1792,7 +1791,7 @@ public class CustomConcurrentHashMap() {
- public Unsafe run() throws Exception {
- return getUnsafePrivileged();
- }});
- } catch (java.security.PrivilegedActionException e) {
- throw e.getCause();
- }
- }
- }
-
- private static Unsafe getUnsafePrivileged()
- throws NoSuchFieldException, IllegalAccessException {
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- return (Unsafe) f.get(null);
- }
-
static {
try {
- _unsafe = getUnsafe();
- tableBase = _unsafe.arrayBaseOffset(Node[].class);
- int s = _unsafe.arrayIndexScale(Node[].class);
- if ((s & (s-1)) != 0)
+ UNSAFE = getUnsafe();
+ tableBase = UNSAFE.arrayBaseOffset(Node[].class);
+ int scale = UNSAFE.arrayIndexScale(Node[].class);
+ if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
- tableShift = 31 - Integer.numberOfLeadingZeros(s);
- segmentsBase = _unsafe.arrayBaseOffset(Segment[].class);
- s = _unsafe.arrayIndexScale(Segment[].class);
- if ((s & (s-1)) != 0)
+ tableShift = 31 - Integer.numberOfLeadingZeros(scale);
+ segmentsBase = UNSAFE.arrayBaseOffset(Segment[].class);
+ scale = UNSAFE.arrayIndexScale(Segment[].class);
+ if ((scale & (scale - 1)) != 0)
throw new Error("data type scale not a power of two");
- segmentsShift = 31 - Integer.numberOfLeadingZeros(s);
+ segmentsShift = 31 - Integer.numberOfLeadingZeros(scale);
} catch (Throwable e) {
throw new RuntimeException("Could not initialize intrinsics", e);
}
}
// Fenced store into segment table array. Unneeded when we have Fences
- static final void storeNode(Node[] table,
- int i, Node r) {
+ static final void storeNode(Node[] table,
+ int i, Node r) {
long nodeOffset = ((long) i << tableShift) + tableBase;
- _unsafe.putOrderedObject(table, nodeOffset, r);
+ UNSAFE.putOrderedObject(table, nodeOffset, r);
}
- static final void storeSegment(Segment[] segs,
- int i, Segment s) {
+ static final void storeSegment(Segment[] segs,
+ int i, Segment s) {
long segmentOffset = ((long) i << segmentsShift) + segmentsBase;
- _unsafe.putOrderedObject(segs, segmentOffset, s);
+ UNSAFE.putOrderedObject(segs, segmentOffset, s);
}
-
+ /**
+ * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
+ * Replace with a simple call to Unsafe.getUnsafe when integrating
+ * into a jdk.
+ *
+ * @return a sun.misc.Unsafe
+ */
+ private static sun.misc.Unsafe getUnsafe() {
+ try {
+ return sun.misc.Unsafe.getUnsafe();
+ } catch (SecurityException tryReflectionInstead) {}
+ try {
+ return java.security.AccessController.doPrivileged
+ (new java.security.PrivilegedExceptionAction() {
+ public sun.misc.Unsafe run() throws Exception {
+ Class k = sun.misc.Unsafe.class;
+ for (java.lang.reflect.Field f : k.getDeclaredFields()) {
+ f.setAccessible(true);
+ Object x = f.get(null);
+ if (k.isInstance(x))
+ return k.cast(x);
+ }
+ throw new NoSuchFieldError("the Unsafe");
+ }});
+ } catch (java.security.PrivilegedActionException e) {
+ throw new RuntimeException("Could not initialize intrinsics",
+ e.getCause());
+ }
+ }
}