@Nullable ReferenceEntry<K, V> removeValueFromChain(ReferenceEntry<K, V> first, @Nonnull ReferenceEntry<K, V> entry, K key, int hash, @Nonnull ValueReference<K, V> valueReference, RemovalCause cause) { enqueueNotification(key, hash, valueReference, cause); writeQueue.remove(entry); accessQueue.remove(entry); if (valueReference.isLoading()) { valueReference.notifyNewValue(null); return first; } else { return removeEntryFromChain(first, entry); } }
@Nullable V scheduleRefresh(@Nonnull ReferenceEntry<K, V> entry, @Nonnull K key, int hash, V oldValue, long now, @Nonnull CacheLoader<? super K, V> loader) { if (map.refreshes() && (now - entry.getWriteTime() > map.refreshNanos) && !entry.getValueReference().isLoading()) { V newValue = refresh(key, hash, loader, true); if (newValue != null) { return newValue; } } return oldValue; }
@Nullable V waitForLoadingValue(@Nonnull ReferenceEntry<K, V> e, K key, @Nonnull ValueReference<K, V> valueReference) throws ExecutionException { if (!valueReference.isLoading()) { throw new AssertionError(); } Preconditions.checkState(!Thread.holdsLock(e), "Recursive load of: %s", key); // don't consider expiration as we're concurrent with loading try { V value = valueReference.waitForValue(); if (value == null) { throw new InvalidCacheLoadException("CacheLoader returned null for key " + key + "."); } // re-read ticker now that loading has completed long now = map.ticker.read(); recordRead(e, now); return value; } finally { } }
&& map.keyEquivalence.equivalent(key, entryKey)) { valueReference = e.getValueReference(); if (valueReference.isLoading()) { createNewEntry = false; } else {
if (valueReference.isLoading() || (checkTime && (now - e.getWriteTime() < map.refreshNanos))) {
if (valueReference.isLoading()) { return waitForLoadingValue(e, key, valueReference);