/** * This method is a convenience for testing. Code should call {@link Segment#setValue} instead. */ // Guarded By Segment.this @Nonnull ValueReference<K, V> newValueReference(@Nonnull ReferenceEntry<K, V> entry, @Nonnull V value, int weight) { int hash = entry.getHash(); return valueStrength.referenceValue(segmentFor(hash), entry, Preconditions.checkNotNull(value), weight); }
/** * This method is a convenience for testing. Code should call {@link Segment#copyEntry} directly. */ // Guarded By Segment.this @Nullable ReferenceEntry<K, V> copyEntry(@Nonnull ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) { int hash = original.getHash(); return segmentFor(hash).copyEntry(original, newNext); }
void expireEntries(long now) { drainRecencyQueue(); ReferenceEntry<K, V> e; while ((e = writeQueue.peek()) != null && map.isExpired(e, now)) { if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) { throw new AssertionError(); } } while ((e = accessQueue.peek()) != null && map.isExpired(e, now)) { if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) { throw new AssertionError(); } } }
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { valueReference = e.getValueReference();
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> valueReference = e.getValueReference();
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) {
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) {
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> valueReference = e.getValueReference();
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> valueReference = e.getValueReference();
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> valueReference = e.getValueReference();
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> valueReference = e.getValueReference();
if (e.getHash() == hash && entryKey != null && map.keyEquivalence.equivalent(key, entryKey)) { ValueReference<K, V> v = e.getValueReference();
/** * Performs eviction if the segment is over capacity. Avoids flushing the entire cache if the * newest entry exceeds the maximum weight all on its own. * * @param newest the most recently added entry */ void evictEntries(@Nonnull ReferenceEntry<K, V> newest) { if (!map.evictsBySize()) { return; } drainRecencyQueue(); // If the newest entry by itself is too heavy for the segment, don't bother evicting // anything else, just that if (newest.getValueReference().getWeight() > maxSegmentWeight) { if (!removeEntry(newest, newest.getHash(), RemovalCause.SIZE)) { throw new AssertionError(); } } while (totalWeight > maxSegmentWeight) { ReferenceEntry<K, V> e = getNextEvictable(); if (!removeEntry(e, e.getHash(), RemovalCause.SIZE)) { throw new AssertionError(); } } }
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(); } }
@Nullable ReferenceEntry<K, V> getEntry(Object key, int hash) { for (ReferenceEntry<K, V> e = getFirst(hash); e != null; e = e.getNext()) { if (e.getHash() != hash) { continue; } K entryKey = e.getKey(); if (entryKey == null) { tryDrainReferenceQueues(); continue; } if (map.keyEquivalence.equivalent(key, entryKey)) { return e; } } return null; }
void enqueueNotification(@Nonnull ReferenceEntry<K, V> entry, RemovalCause cause) { enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference(), cause); }
void reclaimKey(@Nonnull ReferenceEntry<K, V> entry) { int hash = entry.getHash(); segmentFor(hash).reclaimKey(entry, hash); }
void reclaimValue(@Nonnull ValueReference<K, V> valueReference) { ReferenceEntry<K, V> entry = valueReference.getEntry(); int hash = entry.getHash(); segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference); }
/** * This method is a convenience for testing. Code should call {@link Segment#getLiveValue} * instead. */ boolean isLive(@Nonnull ReferenceEntry<K, V> entry, long now) { return segmentFor(entry.getHash()).getLiveValue(entry, now) != null; }
/** * Copies an entry, assigning it a new {@code next} entry. * * @param original the entry to copy * @param newNext entry in the same bucket */ // Guarded By Segment.this <K, V> ReferenceEntry<K, V> copyEntry( Segment<K, V> segment, @Nonnull ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) { return newEntry(segment, original.getKey(), original.getHash(), newNext); }