boolean containsValue(Object value) { if (count != 0) { // read-volatile HashEntry<K,V>[] tab = table; int len = tab.length; for (int i = 0 ; i < len; i++) { for (HashEntry<K,V> e = tab[i]; e != null; e = e.next) { Object opaque = e.valueRef; V v; if (opaque == null) v = readValueUnderLock(e); // recheck else v = e.dereferenceValue(opaque); if (value.equals(v)) return true; } } } return false; }
&& (refRemove || hash != e.hash || !keyEq(key, e.key()))) e = e.next; V v = e.value(); if (value == null || value.equals(v)) { oldValue = v; HashEntry<K,V> newFirst = e.next; for (HashEntry<K,V> p = first; p != e; p = p.next) { K pKey = p.key(); if (pKey == null) { // Skip GC'd keys c--; newFirst = newHashEntry(pKey, p.hash, newFirst, p.value());
boolean replace(K key, int hash, V oldValue, V newValue) { lock(); try { removeStale(); HashEntry<K,V> e = getFirst(hash); while (e != null && (e.hash != hash || !keyEq(key, e.key()))) e = e.next; boolean replaced = false; if (e != null && oldValue.equals(e.value())) { replaced = true; e.setValue(newValue, valueType, refQueue); } return replaced; } finally { unlock(); } }
V replace(K key, int hash, V newValue) { lock(); try { removeStale(); HashEntry<K,V> e = getFirst(hash); while (e != null && (e.hash != hash || !keyEq(key, e.key()))) e = e.next; V oldValue = null; if (e != null) { oldValue = e.value(); e.setValue(newValue, valueType, refQueue); } return oldValue; } finally { unlock(); } }
final void setValue(V value, ReferenceType valueType, ReferenceQueue<Object> refQueue) { this.valueRef = newValueReference(value, valueType, refQueue); }
final V value() { return dereferenceValue(valueRef); }
V get(Object key, int hash) { if (count != 0) { // read-volatile HashEntry<K,V> e = getFirst(hash); while (e != null) { if (e.hash == hash && keyEq(key, e.key())) { Object opaque = e.valueRef; if (opaque != null) return e.dereferenceValue(opaque); return readValueUnderLock(e); // recheck } e = e.next; } } return null; }
/** * Reads value field of an entry under lock. Called if value * field ever appears to be null. This is possible only if a * compiler happens to reorder a HashEntry initialization with * its table assignment, which is legal under memory model * but is not known to ever occur. */ V readValueUnderLock(HashEntry<K,V> e) { lock(); try { removeStale(); return e.value(); } finally { unlock(); } }
HashEntry<K,V> newHashEntry(K key, int hash, HashEntry<K, V> next, V value) { return new HashEntry<K,V>(key, hash, next, value, keyType, valueType, refQueue); }
boolean containsKey(Object key, int hash) { if (count != 0) { // read-volatile HashEntry<K,V> e = getFirst(hash); while (e != null) { if (e.hash == hash && keyEq(key, e.key())) return true; e = e.next; } } return false; }
Segment(int initialCapacity, float lf, ReferenceType keyType, ReferenceType valueType, boolean identityComparisons) { loadFactor = lf; this.keyType = keyType; this.valueType = valueType; this.identityComparisons = identityComparisons; setTable(HashEntry.<K,V>newArray(initialCapacity)); }
HashEntry(K key, int hash, HashEntry<K,V> next, V value, ReferenceType keyType, ReferenceType valueType, ReferenceQueue<Object> refQueue) { this.hash = hash; this.next = next; this.keyRef = newKeyReference(key, keyType, refQueue); this.valueRef = newValueReference(value, valueType, refQueue); }