/** * Copies {@code original} into a new entry chained to {@code newNext}. Returns the new entry, * or {@code null} if {@code original} was already garbage collected. */ @Nullable ReferenceEntry<K, V> copyEntry(@Nonnull ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) { if (original.getKey() == null) { // key collected return null; } ValueReference<K, V> valueReference = original.getValueReference(); V value = valueReference.get(); if ((value == null) && valueReference.isActive()) { // value collected return null; } ReferenceEntry<K, V> newEntry = map.entryFactory.copyEntry(this, original, newNext); newEntry.setValueReference(valueReference.copyFor(this.valueReferenceQueue, value, newEntry)); return newEntry; }
boolean removeLoadingValue(K key, int hash, @Nonnull LoadingValueReference<K, V> valueReference) { lock(); try { AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table; int index = hash & (table.length() - 1); ReferenceEntry<K, V> first = table.get(index); for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) { K entryKey = e.getKey(); if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> v = e.getValueReference(); if (v == valueReference) { if (valueReference.isActive()) { e.setValueReference(valueReference.getOldValue()); } else { ReferenceEntry<K, V> newFirst = removeEntryFromChain(first, e); table.set(index, newFirst); } return true; } return false; } } return false; } finally { unlock(); postWriteCleanup(); } }
e.setValueReference(loadingValueReference); table.set(index, e); } else { e.setValueReference(loadingValueReference);
LoadingValueReference<K, V> loadingValueReference = new LoadingValueReference<>(valueReference); e.setValueReference(loadingValueReference); return loadingValueReference; LoadingValueReference<K, V> loadingValueReference = new LoadingValueReference<>(); e = newEntry(key, hash, first); e.setValueReference(loadingValueReference); table.set(index, e); return loadingValueReference;
/** * Sets a new value of an entry. Adds newly created entries at the end of the access queue. */ void setValue(@Nonnull ReferenceEntry<K, V> entry, K key, V value, long now) { ValueReference<K, V> previous = entry.getValueReference(); int weight = map.weigher.weigh(key, value); Preconditions.checkState(weight >= 0, "Weights must be non-negative"); ValueReference<K, V> valueReference = map.valueStrength.referenceValue(this, entry, value, weight); entry.setValueReference(valueReference); recordWrite(entry, weight, now); previous.notifyNewValue(value); }