All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.common.cache.AbstractCache Maven / Gradle / Ivy

There is a newer version: 33.3.0-jre-r3
Show newest version
/*
 * Copyright (C) 2011 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.common.cache;

import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;

/**
 * This class provides a skeletal implementation of the {@code Cache} interface to minimize the
 * effort required to implement this interface.
 *
 * 

To implement a cache, the programmer needs only to extend this class and provide an * implementation for the {@link #put} and {@link #getIfPresent} methods. {@link #getAllPresent} is * implemented in terms of {@link #getIfPresent}; {@link #putAll} is implemented in terms of {@link * #put}, {@link #invalidateAll(Iterable)} is implemented in terms of {@link #invalidate}. The * method {@link #cleanUp} is a no-op. All other methods throw an {@link * UnsupportedOperationException}. * * @author Charles Fry * @since 10.0 */ @GwtCompatible @ElementTypesAreNonnullByDefault public abstract class AbstractCache implements Cache { /** Constructor for use by subclasses. */ protected AbstractCache() {} /** @since 11.0 */ @Override public V get(K key, Callable valueLoader) throws ExecutionException { throw new UnsupportedOperationException(); } /** * {@inheritDoc} * *

This implementation of {@code getAllPresent} lacks any insight into the internal cache data * structure, and is thus forced to return the query keys instead of the cached keys. This is only * possible with an unsafe cast which requires {@code keys} to actually be of type {@code K}. * * @since 11.0 */ /* * is mostly the same as to plain Java. But to nullness checkers, they * differ: means "non-null types," while means "all types." */ @Override public ImmutableMap getAllPresent(Iterable keys) { Map result = Maps.newLinkedHashMap(); for (Object key : keys) { if (!result.containsKey(key)) { @SuppressWarnings("unchecked") K castKey = (K) key; V value = getIfPresent(key); if (value != null) { result.put(castKey, value); } } } return ImmutableMap.copyOf(result); } /** @since 11.0 */ @Override public void put(K key, V value) { throw new UnsupportedOperationException(); } /** @since 12.0 */ @Override public void putAll(Map m) { for (Entry entry : m.entrySet()) { put(entry.getKey(), entry.getValue()); } } @Override public void cleanUp() {} @Override public long size() { throw new UnsupportedOperationException(); } @Override public void invalidate(Object key) { throw new UnsupportedOperationException(); } /** @since 11.0 */ @Override // For discussion of , see getAllPresent. public void invalidateAll(Iterable keys) { for (Object key : keys) { invalidate(key); } } @Override public void invalidateAll() { throw new UnsupportedOperationException(); } @Override public CacheStats stats() { throw new UnsupportedOperationException(); } @Override public ConcurrentMap asMap() { throw new UnsupportedOperationException(); } /** * Accumulates statistics during the operation of a {@link Cache} for presentation by {@link * Cache#stats}. This is solely intended for consumption by {@code Cache} implementors. * * @since 10.0 */ public interface StatsCounter { /** * Records cache hits. This should be called when a cache request returns a cached value. * * @param count the number of hits to record * @since 11.0 */ void recordHits(int count); /** * Records cache misses. This should be called when a cache request returns a value that was not * found in the cache. This method should be called by the loading thread, as well as by threads * blocking on the load. Multiple concurrent calls to {@link Cache} lookup methods with the same * key on an absent value should result in a single call to either {@code recordLoadSuccess} or * {@code recordLoadException} and multiple calls to this method, despite all being served by * the results of a single load operation. * * @param count the number of misses to record * @since 11.0 */ void recordMisses(int count); /** * Records the successful load of a new entry. This should be called when a cache request causes * an entry to be loaded, and the loading completes successfully. In contrast to {@link * #recordMisses}, this method should only be called by the loading thread. * * @param loadTime the number of nanoseconds the cache spent computing or retrieving the new * value */ @SuppressWarnings("GoodTime") // should accept a java.time.Duration void recordLoadSuccess(long loadTime); /** * Records the failed load of a new entry. This should be called when a cache request causes an * entry to be loaded, but an exception is thrown while loading the entry. In contrast to {@link * #recordMisses}, this method should only be called by the loading thread. * * @param loadTime the number of nanoseconds the cache spent computing or retrieving the new * value prior to an exception being thrown */ @SuppressWarnings("GoodTime") // should accept a java.time.Duration void recordLoadException(long loadTime); /** * Records the eviction of an entry from the cache. This should only been called when an entry * is evicted due to the cache's eviction strategy, and not as a result of manual {@linkplain * Cache#invalidate invalidations}. */ void recordEviction(); /** * Returns a snapshot of this counter's values. Note that this may be an inconsistent view, as * it may be interleaved with update operations. */ CacheStats snapshot(); } /** * A thread-safe {@link StatsCounter} implementation for use by {@link Cache} implementors. * * @since 10.0 */ public static final class SimpleStatsCounter implements StatsCounter { private final LongAddable hitCount = LongAddables.create(); private final LongAddable missCount = LongAddables.create(); private final LongAddable loadSuccessCount = LongAddables.create(); private final LongAddable loadExceptionCount = LongAddables.create(); private final LongAddable totalLoadTime = LongAddables.create(); private final LongAddable evictionCount = LongAddables.create(); /** Constructs an instance with all counts initialized to zero. */ public SimpleStatsCounter() {} /** @since 11.0 */ @Override public void recordHits(int count) { hitCount.add(count); } /** @since 11.0 */ @Override public void recordMisses(int count) { missCount.add(count); } @SuppressWarnings("GoodTime") // b/122668874 @Override public void recordLoadSuccess(long loadTime) { loadSuccessCount.increment(); totalLoadTime.add(loadTime); } @SuppressWarnings("GoodTime") // b/122668874 @Override public void recordLoadException(long loadTime) { loadExceptionCount.increment(); totalLoadTime.add(loadTime); } @Override public void recordEviction() { evictionCount.increment(); } @Override public CacheStats snapshot() { return new CacheStats( negativeToMaxValue(hitCount.sum()), negativeToMaxValue(missCount.sum()), negativeToMaxValue(loadSuccessCount.sum()), negativeToMaxValue(loadExceptionCount.sum()), negativeToMaxValue(totalLoadTime.sum()), negativeToMaxValue(evictionCount.sum())); } /** Returns {@code value}, if non-negative. Otherwise, returns {@link Long#MAX_VALUE}. */ private static long negativeToMaxValue(long value) { return (value >= 0) ? value : Long.MAX_VALUE; } /** Increments all counters by the values in {@code other}. */ public void incrementBy(StatsCounter other) { CacheStats otherStats = other.snapshot(); hitCount.add(otherStats.hitCount()); missCount.add(otherStats.missCount()); loadSuccessCount.add(otherStats.loadSuccessCount()); loadExceptionCount.add(otherStats.loadExceptionCount()); totalLoadTime.add(otherStats.totalLoadTime()); evictionCount.add(otherStats.evictionCount()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy