aboutsummaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/cache
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/cache')
-rw-r--r--guava/src/com/google/common/cache/AbstractCache.java110
-rw-r--r--guava/src/com/google/common/cache/AbstractLoadingCache.java9
-rw-r--r--guava/src/com/google/common/cache/Cache.java82
-rw-r--r--guava/src/com/google/common/cache/CacheBuilder.java195
-rw-r--r--guava/src/com/google/common/cache/CacheBuilderSpec.java455
-rw-r--r--guava/src/com/google/common/cache/CacheLoader.java58
-rw-r--r--guava/src/com/google/common/cache/CacheStats.java7
-rw-r--r--guava/src/com/google/common/cache/ForwardingCache.java31
-rw-r--r--guava/src/com/google/common/cache/LoadingCache.java9
-rw-r--r--guava/src/com/google/common/cache/LocalCache.java369
-rw-r--r--guava/src/com/google/common/cache/LongAddable.java33
-rw-r--r--guava/src/com/google/common/cache/LongAddables.java75
-rw-r--r--guava/src/com/google/common/cache/LongAdder.java211
-rw-r--r--guava/src/com/google/common/cache/RemovalCause.java2
-rw-r--r--guava/src/com/google/common/cache/RemovalListener.java2
-rw-r--r--guava/src/com/google/common/cache/RemovalListeners.java4
-rw-r--r--guava/src/com/google/common/cache/RemovalNotification.java2
-rw-r--r--guava/src/com/google/common/cache/Striped64.java347
-rw-r--r--guava/src/com/google/common/cache/Weigher.java19
-rw-r--r--guava/src/com/google/common/cache/package-info.java4
20 files changed, 406 insertions, 1618 deletions
diff --git a/guava/src/com/google/common/cache/AbstractCache.java b/guava/src/com/google/common/cache/AbstractCache.java
index a8af810..8ce941d 100644
--- a/guava/src/com/google/common/cache/AbstractCache.java
+++ b/guava/src/com/google/common/cache/AbstractCache.java
@@ -20,21 +20,22 @@ import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
+import com.google.common.util.concurrent.UncheckedExecutionException;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLong;
/**
* This class provides a skeletal implementation of the {@code Cache} interface to minimize the
* effort required to implement this interface.
*
* <p>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
+ * implementation for the {@link #getIfPresent} method. {@link #getAllPresent} is implemented in
+ * terms of {@code getIfPresent}; {@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
@@ -56,22 +57,14 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
}
/**
- * 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}.
- *
- * {@inheritDoc}
- *
* @since 11.0
*/
@Override
- public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
+ public ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys) {
Map<K, V> result = Maps.newLinkedHashMap();
- for (Object key : keys) {
+ for (K key : keys) {
if (!result.containsKey(key)) {
- @SuppressWarnings("unchecked")
- K castKey = (K) key;
- result.put(castKey, getIfPresent(key));
+ result.put(key, getIfPresent(key));
}
}
return ImmutableMap.copyOf(result);
@@ -85,16 +78,6 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
throw new UnsupportedOperationException();
}
- /**
- * @since 12.0
- */
- @Override
- public void putAll(Map<? extends K, ? extends V> m) {
- for (Map.Entry<? extends K, ? extends V> entry : m.entrySet()) {
- put(entry.getKey(), entry.getValue());
- }
- }
-
@Override
public void cleanUp() {}
@@ -133,6 +116,22 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
throw new UnsupportedOperationException();
}
+ @Deprecated
+ @Override
+ public V getUnchecked(K key) {
+ try {
+ return get(key);
+ } catch (ExecutionException e) {
+ throw new UncheckedExecutionException(e.getCause());
+ }
+ }
+
+ @Deprecated
+ @Override
+ public V apply(K key) {
+ return getUnchecked(key);
+ }
+
/**
* 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.
@@ -165,7 +164,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
/**
* 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.
+ * {@link #recordConcurrentMiss}, 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
@@ -175,7 +174,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
/**
* 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.
+ * {@link #recordConcurrentMiss}, 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
@@ -202,25 +201,20 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
* @since 10.0
*/
@Beta
- 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() {}
+ public static class SimpleStatsCounter implements StatsCounter {
+ private final AtomicLong hitCount = new AtomicLong();
+ private final AtomicLong missCount = new AtomicLong();
+ private final AtomicLong loadSuccessCount = new AtomicLong();
+ private final AtomicLong loadExceptionCount = new AtomicLong();
+ private final AtomicLong totalLoadTime = new AtomicLong();
+ private final AtomicLong evictionCount = new AtomicLong();
/**
* @since 11.0
*/
@Override
public void recordHits(int count) {
- hitCount.add(count);
+ hitCount.addAndGet(count);
}
/**
@@ -228,35 +222,35 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
*/
@Override
public void recordMisses(int count) {
- missCount.add(count);
+ missCount.addAndGet(count);
}
@Override
public void recordLoadSuccess(long loadTime) {
- loadSuccessCount.increment();
- totalLoadTime.add(loadTime);
+ loadSuccessCount.incrementAndGet();
+ totalLoadTime.addAndGet(loadTime);
}
@Override
public void recordLoadException(long loadTime) {
- loadExceptionCount.increment();
- totalLoadTime.add(loadTime);
+ loadExceptionCount.incrementAndGet();
+ totalLoadTime.addAndGet(loadTime);
}
@Override
public void recordEviction() {
- evictionCount.increment();
+ evictionCount.incrementAndGet();
}
@Override
public CacheStats snapshot() {
return new CacheStats(
- hitCount.sum(),
- missCount.sum(),
- loadSuccessCount.sum(),
- loadExceptionCount.sum(),
- totalLoadTime.sum(),
- evictionCount.sum());
+ hitCount.get(),
+ missCount.get(),
+ loadSuccessCount.get(),
+ loadExceptionCount.get(),
+ totalLoadTime.get(),
+ evictionCount.get());
}
/**
@@ -264,12 +258,12 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
*/
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());
+ hitCount.addAndGet(otherStats.hitCount());
+ missCount.addAndGet(otherStats.missCount());
+ loadSuccessCount.addAndGet(otherStats.loadSuccessCount());
+ loadExceptionCount.addAndGet(otherStats.loadExceptionCount());
+ totalLoadTime.addAndGet(otherStats.totalLoadTime());
+ evictionCount.addAndGet(otherStats.evictionCount());
}
}
}
diff --git a/guava/src/com/google/common/cache/AbstractLoadingCache.java b/guava/src/com/google/common/cache/AbstractLoadingCache.java
index 6a12c40..22ef81b 100644
--- a/guava/src/com/google/common/cache/AbstractLoadingCache.java
+++ b/guava/src/com/google/common/cache/AbstractLoadingCache.java
@@ -30,11 +30,10 @@ import java.util.concurrent.ExecutionException;
* effort required to implement this interface.
*
* <p>To implement a cache, the programmer needs only to extend this class and provide an
- * implementation for the {@link #get(Object)} and {@link #getIfPresent} methods.
- * {@link #getUnchecked}, {@link #get(Object, Callable)}, and {@link #getAll} are implemented in
- * terms of {@code get}; {@link #getAllPresent} is implemented in terms of {@code 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
+ * implementation for the {@link #get} and {@link #getIfPresent} methods. {@link #getUnchecked},
+ * {@link #get(K, Callable)}, and {@link #getAll} are implemented in terms of {@code get};
+ * {@link #getAllPresent} is implemented in terms of {@code get}; {@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
diff --git a/guava/src/com/google/common/cache/Cache.java b/guava/src/com/google/common/cache/Cache.java
index cfe5764..f243adc 100644
--- a/guava/src/com/google/common/cache/Cache.java
+++ b/guava/src/com/google/common/cache/Cache.java
@@ -18,11 +18,11 @@ package com.google.common.cache;
import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.ExecutionError;
import com.google.common.util.concurrent.UncheckedExecutionException;
-import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
@@ -31,23 +31,24 @@ import javax.annotation.Nullable;
/**
* A semi-persistent mapping from keys to values. Cache entries are manually added using
- * {@link #get(Object, Callable)} or {@link #put(Object, Object)}, and are stored in the cache until
- * either evicted or manually invalidated.
+ * {@link #get(K, Callable)} or {@link #put(K, V)}, and are stored in the cache until either
+ * evicted or manually invalidated.
+ *
+ * <p><b>Note:</b> in release 12.0, all methods moved from {@code Cache} to {@link LoadingCache}
+ * will be deleted from {@code Cache}. As part of this transition {@code Cache} will no longer
+ * extend {@link Function}.
*
* <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
* by multiple concurrent threads.
*
- * <p>Note that while this class is still annotated as {@link Beta}, the API is frozen from a
- * consumer's standpoint. In other words existing methods are all considered {@code non-Beta} and
- * won't be changed without going through an 18 month deprecation cycle; however new methods may be
- * added at any time.
+ * <p>All methods other than {@link #getIfPresent} are optional.
*
* @author Charles Fry
* @since 10.0
*/
@Beta
@GwtCompatible
-public interface Cache<K, V> {
+public interface Cache<K, V> extends Function<K, V> {
/**
* Returns the value associated with {@code key} in this cache, or {@code null} if there is no
@@ -56,7 +57,7 @@ public interface Cache<K, V> {
* @since 11.0
*/
@Nullable
- V getIfPresent(Object key);
+ V getIfPresent(K key);
/**
* Returns the value associated with {@code key} in this cache, obtaining that value from
@@ -82,7 +83,7 @@ public interface Cache<K, V> {
*
* @since 11.0
*/
- ImmutableMap<K, V> getAllPresent(Iterable<?> keys);
+ ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys);
/**
* Associates {@code value} with {@code key} in this cache. If the cache previously contained a
@@ -96,16 +97,6 @@ public interface Cache<K, V> {
void put(K key, V value);
/**
- * Copies all of the mappings from the specified map to the cache. The effect of this call is
- * equivalent to that of calling {@code put(k, v)} on this map once for each mapping from key
- * {@code k} to value {@code v} in the specified map. The behavior of this operation is undefined
- * if the specified map is modified while the operation is in progress.
- *
- * @since 12.0
- */
- void putAll(Map<? extends K,? extends V> m);
-
- /**
* Discards any cached value for key {@code key}.
*/
void invalidate(Object key);
@@ -144,4 +135,55 @@ public interface Cache<K, V> {
* performed -- if any -- is implementation-dependent.
*/
void cleanUp();
+
+ /**
+ * Returns the value associated with {@code key} in this cache, first loading that value if
+ * necessary. No observable state associated with this cache is modified until loading completes.
+ *
+ * @throws ExecutionException if a checked exception was thrown while loading the value
+ * @throws UncheckedExecutionException if an unchecked exception was thrown while loading the
+ * value
+ * @throws ExecutionError if an error was thrown while loading the value
+ * @deprecated This method has been split out into the {@link LoadingCache} interface, and will be
+ * removed from {@code Cache} in Guava release 12.0. Note that
+ * {@link CacheBuilder#build(CacheLoader)} now returns a {@code LoadingCache}, so this deprecation
+ * (migration) can be dealt with by simply changing the type of references to the results of
+ * {@link CacheBuilder#build(CacheLoader)}.
+ */
+ @Deprecated V get(K key) throws ExecutionException;
+
+ /**
+ * Returns the value associated with {@code key} in this cache, first loading that value if
+ * necessary. No observable state associated with this cache is modified until computation
+ * completes. Unlike {@link #get}, this method does not throw a checked exception, and thus should
+ * only be used in situations where checked exceptions are not thrown by the cache loader.
+ *
+ * <p><b>Warning:</b> this method silently converts checked exceptions to unchecked exceptions,
+ * and should not be used with cache loaders which throw checked exceptions.
+ *
+ * @throws UncheckedExecutionException if an exception was thrown while loading the value,
+ * regardless of whether the exception was checked or unchecked
+ * @throws ExecutionError if an error was thrown while loading the value
+ * @deprecated This method has been split out into the {@link LoadingCache} interface, and will be
+ * removed from {@code Cache} in Guava release 12.0. Note that
+ * {@link CacheBuilder#build(CacheLoader)} now returns a {@code LoadingCache}, so this deprecation
+ * (migration) can be dealt with by simply changing the type of references to the results of
+ * {@link CacheBuilder#build(CacheLoader)}.
+ */
+ @Deprecated V getUnchecked(K key);
+
+ /**
+ * Discouraged. Provided to satisfy the {@code Function} interface; use {@link #get} or
+ * {@link #getUnchecked} instead.
+ *
+ * @throws UncheckedExecutionException if an exception was thrown while loading the value,
+ * regardless of whether the exception was checked or unchecked
+ * @throws ExecutionError if an error was thrown while loading the value
+ * @deprecated This method has been split out into the {@link LoadingCache} interface, and will be
+ * removed from {@code Cache} in Guava release 12.0. Note that
+ * {@link CacheBuilder#build(CacheLoader)} now returns a {@code LoadingCache}, so this deprecation
+ * (migration) can be dealt with by simply changing the type of references to the results of
+ * {@link CacheBuilder#build(CacheLoader)}.
+ */
+ @Deprecated V apply(K key);
}
diff --git a/guava/src/com/google/common/cache/CacheBuilder.java b/guava/src/com/google/common/cache/CacheBuilder.java
index 105ff73..8eef200 100644
--- a/guava/src/com/google/common/cache/CacheBuilder.java
+++ b/guava/src/com/google/common/cache/CacheBuilder.java
@@ -26,6 +26,7 @@ import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Ascii;
import com.google.common.base.Equivalence;
+import com.google.common.base.Equivalences;
import com.google.common.base.Objects;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
@@ -56,12 +57,8 @@ import javax.annotation.CheckReturnValue;
* <li>values automatically wrapped in {@linkplain WeakReference weak} or
* {@linkplain SoftReference soft} references
* <li>notification of evicted (or otherwise removed) entries
- * <li>accumulation of cache access statistics
* </ul>
*
- * These features are all optional; caches can be created using all or none of them. By default
- * cache instances created by {@code CacheBuilder} will not perform any type of eviction.
- *
* <p>Usage example: <pre> {@code
*
* LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
@@ -75,19 +72,8 @@ import javax.annotation.CheckReturnValue;
* }
* });}</pre>
*
- * Or equivalently, <pre> {@code
- *
- * // In real life this would come from a command-line flag or config file
- * String spec = "maximumSize=10000,expireAfterWrite=10m";
*
- * LoadingCache<Key, Graph> graphs = CacheBuilder.from(spec)
- * .removalListener(MY_LISTENER)
- * .build(
- * new CacheLoader<Key, Graph>() {
- * public Graph load(Key key) throws AnyException {
- * return createExpensiveGraph(key);
- * }
- * });}</pre>
+ * These features are all optional.
*
* <p>The returned cache is implemented as a hash table with similar performance characteristics to
* {@link ConcurrentHashMap}. It implements all optional operations of the {@link LoadingCache} and
@@ -139,16 +125,13 @@ import javax.annotation.CheckReturnValue;
* retain all the configuration properties of the original cache. Note that the serialized form does
* <i>not</i> include cache contents, but only configuration.
*
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caching</a> for a higher-level
- * explanation.
- *
* @param <K> the base key type for all caches created by this builder
* @param <V> the base value type for all caches created by this builder
* @author Charles Fry
* @author Kevin Bourrillion
* @since 10.0
*/
+@Beta
@GwtCompatible(emulated = true)
public final class CacheBuilder<K, V> {
private static final int DEFAULT_INITIAL_CAPACITY = 16;
@@ -180,10 +163,10 @@ public final class CacheBuilder<K, V> {
});
static final CacheStats EMPTY_STATS = new CacheStats(0, 0, 0, 0, 0, 0);
- static final Supplier<StatsCounter> CACHE_STATS_COUNTER =
- new Supplier<StatsCounter>() {
+ static final Supplier<SimpleStatsCounter> CACHE_STATS_COUNTER =
+ new Supplier<SimpleStatsCounter>() {
@Override
- public StatsCounter get() {
+ public SimpleStatsCounter get() {
return new SimpleStatsCounter();
}
};
@@ -236,7 +219,7 @@ public final class CacheBuilder<K, V> {
RemovalListener<? super K, ? super V> removalListener;
Ticker ticker;
- Supplier<? extends StatsCounter> statsCounterSupplier = NULL_STATS_COUNTER;
+ Supplier<? extends StatsCounter> statsCounterSupplier = CACHE_STATS_COUNTER;
// TODO(fry): make constructor private and update tests to use newBuilder
CacheBuilder() {}
@@ -250,34 +233,8 @@ public final class CacheBuilder<K, V> {
}
/**
- * Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}.
- *
- * @since 12.0
- */
- @Beta
- @GwtIncompatible("To be supported")
- public static CacheBuilder<Object, Object> from(CacheBuilderSpec spec) {
- return spec.toCacheBuilder()
- .lenientParsing();
- }
-
- /**
- * Constructs a new {@code CacheBuilder} instance with the settings specified in {@code spec}.
- * This is especially useful for command-line configuration of a {@code CacheBuilder}.
- *
- * @param spec a String in the format specified by {@link CacheBuilderSpec}
- * @since 12.0
- */
- @Beta
- @GwtIncompatible("To be supported")
- public static CacheBuilder<Object, Object> from(String spec) {
- return from(CacheBuilderSpec.parse(spec));
- }
-
- /**
* Enables lenient parsing. Useful for tests and spec parsing.
*/
- @GwtIncompatible("To be supported")
CacheBuilder<K, V> lenientParsing() {
strictParsing = false;
return this;
@@ -286,10 +243,9 @@ public final class CacheBuilder<K, V> {
/**
* Sets a custom {@code Equivalence} strategy for comparing keys.
*
- * <p>By default, the cache uses {@link Equivalence#identity} to determine key equality when
- * {@link #weakKeys} is specified, and {@link Equivalence#equals()} otherwise.
+ * <p>By default, the cache uses {@link Equivalences#identity} to determine key equality when
+ * {@link #weakKeys} is specified, and {@link Equivalences#equals()} otherwise.
*/
- @GwtIncompatible("To be supported")
CacheBuilder<K, V> keyEquivalence(Equivalence<Object> equivalence) {
checkState(keyEquivalence == null, "key equivalence was already set to %s", keyEquivalence);
keyEquivalence = checkNotNull(equivalence);
@@ -303,11 +259,10 @@ public final class CacheBuilder<K, V> {
/**
* Sets a custom {@code Equivalence} strategy for comparing values.
*
- * <p>By default, the cache uses {@link Equivalence#identity} to determine value equality when
- * {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalence#equals()}
+ * <p>By default, the cache uses {@link Equivalences#identity} to determine value equality when
+ * {@link #weakValues} or {@link #softValues} is specified, and {@link Equivalences#equals()}
* otherwise.
*/
- @GwtIncompatible("To be supported")
CacheBuilder<K, V> valueEquivalence(Equivalence<Object> equivalence) {
checkState(valueEquivalence == null,
"value equivalence was already set to %s", valueEquivalence);
@@ -350,23 +305,11 @@ public final class CacheBuilder<K, V> {
* higher value than you need can waste space and time, and a significantly lower value can lead
* to thread contention. But overestimates and underestimates within an order of magnitude do not
* usually have much noticeable impact. A value of one permits only one thread to modify the cache
- * at a time, but since read operations and cache loading computations can proceed concurrently,
- * this still yields higher concurrency than full synchronization.
- *
- * <p> Defaults to 4. <b>Note:</b>The default may change in the future. If you care about this
- * value, you should always choose it explicitly.
- *
- * <p>The current implementation uses the concurrency level to create a fixed number of hashtable
- * segments, each governed by its own write lock. The segment lock is taken once for each explicit
- * write, and twice for each cache loading computation (once prior to loading the new value,
- * and once after loading completes). Much internal cache management is performed at the segment
- * granularity. For example, access queues and write queues are kept per segment when they are
- * required by the selected eviction algorithm. As such, when writing unit tests it is not
- * uncommon to specify {@code concurrencyLevel(1)} in order to achieve more deterministic eviction
- * behavior.
+ * at a time, but since read operations can proceed concurrently, this still yields higher
+ * concurrency than full synchronization. Defaults to 4.
*
- * <p>Note that future implementations may abandon segment locking in favor of more advanced
- * concurrency controls.
+ * <p><b>Note:</b>The default may change in the future. If you care about this value, you should
+ * always choose it explicitly.
*
* @throws IllegalArgumentException if {@code concurrencyLevel} is nonpositive
* @throws IllegalStateException if a concurrency level was already set
@@ -392,11 +335,9 @@ public final class CacheBuilder<K, V> {
* <p>When {@code size} is zero, elements will be evicted immediately after being loaded into the
* cache. This can be useful in testing, or to disable caching temporarily without a code change.
*
- * <p>This feature cannot be used in conjunction with {@link #maximumWeight}.
- *
* @param size the maximum size of the cache
* @throws IllegalArgumentException if {@code size} is negative
- * @throws IllegalStateException if a maximum size or weight was already set
+ * @throws IllegalStateException if a maximum size was already set
*/
public CacheBuilder<K, V> maximumSize(long size) {
checkState(this.maximumSize == UNSET_INT, "maximum size was already set to %s",
@@ -423,17 +364,11 @@ public final class CacheBuilder<K, V> {
* cache. This can be useful in testing, or to disable caching temporarily without a code
* change.
*
- * <p>Note that weight is only used to determine whether the cache is over capacity; it has no
- * effect on selecting which entry should be evicted next.
- *
- * <p>This feature cannot be used in conjunction with {@link #maximumSize}.
- *
- * @param weight the maximum total weight of entries the cache may contain
- * @throws IllegalArgumentException if {@code weight} is negative
- * @throws IllegalStateException if a maximum weight or size was already set
+ * @param weight the maximum weight the cache may contain
+ * @throws IllegalArgumentException if {@code size} is negative
+ * @throws IllegalStateException if a maximum size was already set
* @since 11.0
*/
- @GwtIncompatible("To be supported")
public CacheBuilder<K, V> maximumWeight(long weight) {
checkState(this.maximumWeight == UNSET_INT, "maximum weight was already set to %s",
this.maximumWeight);
@@ -472,7 +407,6 @@ public final class CacheBuilder<K, V> {
* @throws IllegalStateException if a maximum size was already set
* @since 11.0
*/
- @GwtIncompatible("To be supported")
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> weigher(
Weigher<? super K1, ? super V1> weigher) {
checkState(this.weigher == null);
@@ -502,6 +436,15 @@ public final class CacheBuilder<K, V> {
}
/**
+ * Specifies that each key (not value) stored in the cache should be strongly referenced.
+ *
+ * @throws IllegalStateException if the key strength was already set
+ */
+ CacheBuilder<K, V> strongKeys() {
+ return setKeyStrength(Strength.STRONG);
+ }
+
+ /**
* Specifies that each key (not value) stored in the cache should be wrapped in a {@link
* WeakReference} (by default, strong references are used).
*
@@ -530,6 +473,15 @@ public final class CacheBuilder<K, V> {
}
/**
+ * Specifies that each value (not key) stored in the cache should be strongly referenced.
+ *
+ * @throws IllegalStateException if the value strength was already set
+ */
+ CacheBuilder<K, V> strongValues() {
+ return setValueStrength(Strength.STRONG);
+ }
+
+ /**
* Specifies that each value (not key) stored in the cache should be wrapped in a
* {@link WeakReference} (by default, strong references are used).
*
@@ -657,9 +609,8 @@ public final class CacheBuilder<K, V> {
* {@link CacheLoader#reload}.
*
* <p>As the default implementation of {@link CacheLoader#reload} is synchronous, it is
- * recommended that users of this method override {@link CacheLoader#reload} with an asynchronous
- * implementation; otherwise refreshes will be performed during unrelated cache read and write
- * operations.
+ * recommended that users of this method override {@link CacheLoader#reload} with an asynchrnous
+ * implementation; otherwise refreshes will block other cache operations.
*
* <p>Currently automatic refreshes are performed when the first stale request for an entry
* occurs. The request triggering refresh will make a blocking call to {@link CacheLoader#reload}
@@ -675,8 +626,7 @@ public final class CacheBuilder<K, V> {
* @throws IllegalStateException if the refresh interval was already set
* @since 11.0
*/
- @Beta
- @GwtIncompatible("To be supported (synchronously).")
+ @GwtIncompatible("To be supported")
public CacheBuilder<K, V> refreshAfterWrite(long duration, TimeUnit unit) {
checkNotNull(unit);
checkState(refreshNanos == UNSET_INT, "refresh was already set to %s ns", refreshNanos);
@@ -698,6 +648,7 @@ public final class CacheBuilder<K, V> {
*
* @throws IllegalStateException if a ticker was already set
*/
+ @GwtIncompatible("To be supported")
public CacheBuilder<K, V> ticker(Ticker ticker) {
checkState(this.ticker == null);
this.ticker = checkNotNull(ticker);
@@ -712,27 +663,34 @@ public final class CacheBuilder<K, V> {
}
/**
- * Specifies a listener instance that caches should notify each time an entry is removed for any
- * {@linkplain RemovalCause reason}. Each cache created by this builder will invoke this listener
- * as part of the routine maintenance described in the class documentation above.
- *
- * <p><b>Warning:</b> after invoking this method, do not continue to use <i>this</i> cache
- * builder reference; instead use the reference this method <i>returns</i>. At runtime, these
- * point to the same instance, but only the returned reference has the correct generic type
- * information so as to ensure type safety. For best results, use the standard method-chaining
- * idiom illustrated in the class documentation above, configuring a builder and building your
- * cache in a single statement. Failure to heed this advice can result in a {@link
- * ClassCastException} being thrown by a cache operation at some <i>undefined</i> point in the
- * future.
- *
- * <p><b>Warning:</b> any exception thrown by {@code listener} will <i>not</i> be propagated to
- * the {@code Cache} user, only logged via a {@link Logger}.
- *
- * @return the cache builder reference that should be used instead of {@code this} for any
- * remaining configuration and cache building
+ * Specifies a listener instance, which all caches built using this {@code CacheBuilder} will
+ * notify each time an entry is removed from the cache by any means.
+ *
+ * <p>Each cache built by this {@code CacheBuilder} after this method is called invokes the
+ * supplied listener after removing an element for any reason (see removal causes in {@link
+ * RemovalCause}). It will invoke the listener as part of the routine maintenance described
+ * in the class javadoc.
+ *
+ * <p><b>Note:</b> <i>all exceptions thrown by {@code listener} will be logged (using
+ * {@link java.util.logging.Logger})and then swallowed</i>.
+ *
+ * <p><b>Important note:</b> Instead of returning <em>this</em> as a {@code CacheBuilder}
+ * instance, this method returns {@code CacheBuilder<K1, V1>}. From this point on, either the
+ * original reference or the returned reference may be used to complete configuration and build
+ * the cache, but only the "generic" one is type-safe. That is, it will properly prevent you from
+ * building caches whose key or value types are incompatible with the types accepted by the
+ * listener already provided; the {@code CacheBuilder} type cannot do this. For best results,
+ * simply use the standard method-chaining idiom, as illustrated in the documentation at top,
+ * configuring a {@code CacheBuilder} and building your {@link Cache} all in a single statement.
+ *
+ * <p><b>Warning:</b> if you ignore the above advice, and use this {@code CacheBuilder} to build
+ * a cache whose key or value type is incompatible with the listener, you will likely experience
+ * a {@link ClassCastException} at some <i>undefined</i> point in the future.
+ *
* @throws IllegalStateException if a removal listener was already set
*/
@CheckReturnValue
+ @GwtIncompatible("To be supported")
public <K1 extends K, V1 extends V> CacheBuilder<K1, V1> removalListener(
RemovalListener<? super K1, ? super V1> listener) {
checkState(this.removalListener == null);
@@ -751,15 +709,11 @@ public final class CacheBuilder<K, V> {
}
/**
- * Enable the accumulation of {@link CacheStats} during the operation of the cache. Without this
- * {@link Cache#stats} will return zero for all statistics. Note that recording stats requires
- * bookkeeping to be performed with each operation, and thus imposes a performance penalty on
- * cache operation.
- *
- * @since 12.0 (previously, stats collection was automatic)
+ * Disable the accumulation of {@link CacheStats} during the operation of the cache.
*/
- public CacheBuilder<K, V> recordStats() {
- statsCounterSupplier = CACHE_STATS_COUNTER;
+ CacheBuilder<K, V> disableStats() {
+ checkState(statsCounterSupplier == CACHE_STATS_COUNTER);
+ statsCounterSupplier = NULL_STATS_COUNTER;
return this;
}
@@ -834,11 +788,12 @@ public final class CacheBuilder<K, V> {
if (concurrencyLevel != UNSET_INT) {
s.add("concurrencyLevel", concurrencyLevel);
}
- if (maximumSize != UNSET_INT) {
- s.add("maximumSize", maximumSize);
- }
if (maximumWeight != UNSET_INT) {
- s.add("maximumWeight", maximumWeight);
+ if (weigher == null) {
+ s.add("maximumSize", maximumWeight);
+ } else {
+ s.add("maximumWeight", maximumWeight);
+ }
}
if (expireAfterWriteNanos != UNSET_INT) {
s.add("expireAfterWrite", expireAfterWriteNanos + "ns");
diff --git a/guava/src/com/google/common/cache/CacheBuilderSpec.java b/guava/src/com/google/common/cache/CacheBuilderSpec.java
deleted file mode 100644
index 1e03335..0000000
--- a/guava/src/com/google/common/cache/CacheBuilderSpec.java
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * 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 static com.google.common.base.Preconditions.checkArgument;
-
-import com.google.common.annotations.Beta;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Splitter;
-import com.google.common.cache.LocalCache.Strength;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import javax.annotation.Nullable;
-
-/**
- * A specification of a {@link CacheBuilder} configuration.
- *
- * <p>{@code CacheBuilderSpec} supports parsing configuration off of a string, which
- * makes it especially useful for command-line configuration of a {@code CacheBuilder}.
- *
- * <p>The string syntax is a series of comma-separated keys or key-value pairs,
- * each corresponding to a {@code CacheBuilder} method.
- * <ul>
- * <li>{@code concurrencyLevel=[integer]}: sets {@link CacheBuilder#concurrencyLevel}.
- * <li>{@code initialCapacity=[integer]}: sets {@link CacheBuilder#initialCapacity}.
- * <li>{@code maximumSize=[long]}: sets {@link CacheBuilder#maximumSize}.
- * <li>{@code maximumWeight=[long]}: sets {@link CacheBuilder#maximumWeight}.
- * <li>{@code expireAfterAccess=[duration]}: sets {@link CacheBuilder#expireAfterAccess}.
- * <li>{@code expireAfterWrite=[duration]}: sets {@link CacheBuilder#expireAfterWrite}.
- * <li>{@code refreshAfterWrite=[duration]}: sets {@link CacheBuilder#refreshAfterWrite}.
- * <li>{@code weakKeys}: sets {@link CacheBuilder#weakKeys}.
- * <li>{@code softValues}: sets {@link CacheBuilder#softValues}.
- * <li>{@code weakValues}: sets {@link CacheBuilder#weakValues}.
- * </ul>
- *
- * The set of supported keys will grow as {@code CacheBuilder} evolves, but existing keys
- * will never be removed.
- *
- * <p>Durations are represented by an integer, followed by one of "d", "h", "m",
- * or "s", representing days, hours, minutes, or seconds respectively. (There
- * is currently no syntax to request expiration in milliseconds, microseconds,
- * or nanoseconds.)
- *
- * <p>Whitespace before and after commas and equal signs is ignored. Keys may
- * not be repeated; it is also illegal to use the following pairs of keys in
- * a single value:
- * <ul>
- * <li>{@code maximumSize} and {@code maximumWeight}
- * <li>{@code softValues} and {@code weakValues}
- * </ul>
- *
- * <p>{@code CacheBuilderSpec} does not support configuring {@code CacheBuilder} methods
- * with non-value parameters. These must be configured in code.
- *
- * <p>A new {@code CacheBuilder} can be instantiated from a {@code CacheBuilderSpec} using
- * {@link CacheBuilder#from(CacheBuilderSpec)} or {@link CacheBuilder#from(String)}.
- *
- * @author Adam Winer
- * @since 12.0
- */
-@Beta
-public final class CacheBuilderSpec {
- /** Parses a single value. */
- private interface ValueParser {
- void parse(CacheBuilderSpec spec, String key, @Nullable String value);
- }
-
- /** Splits each key-value pair. */
- private static final Splitter KEYS_SPLITTER = Splitter.on(',').trimResults();
-
- /** Splits the key from the value. */
- private static final Splitter KEY_VALUE_SPLITTER = Splitter.on('=').trimResults();
-
- /** Map of names to ValueParser. */
- private static final ImmutableMap<String, ValueParser> VALUE_PARSERS =
- ImmutableMap.<String, ValueParser>builder()
- .put("initialCapacity", new InitialCapacityParser())
- .put("maximumSize", new MaximumSizeParser())
- .put("maximumWeight", new MaximumWeightParser())
- .put("concurrencyLevel", new ConcurrencyLevelParser())
- .put("weakKeys", new KeyStrengthParser(Strength.WEAK))
- .put("softValues", new ValueStrengthParser(Strength.SOFT))
- .put("weakValues", new ValueStrengthParser(Strength.WEAK))
- .put("expireAfterAccess", new AccessDurationParser())
- .put("expireAfterWrite", new WriteDurationParser())
- .put("refreshAfterWrite", new RefreshDurationParser())
- .put("refreshInterval", new RefreshDurationParser())
- .build();
-
- @VisibleForTesting Integer initialCapacity;
- @VisibleForTesting Long maximumSize;
- @VisibleForTesting Long maximumWeight;
- @VisibleForTesting Integer concurrencyLevel;
- @VisibleForTesting Strength keyStrength;
- @VisibleForTesting Strength valueStrength;
- @VisibleForTesting long writeExpirationDuration;
- @VisibleForTesting TimeUnit writeExpirationTimeUnit;
- @VisibleForTesting long accessExpirationDuration;
- @VisibleForTesting TimeUnit accessExpirationTimeUnit;
- @VisibleForTesting long refreshDuration;
- @VisibleForTesting TimeUnit refreshTimeUnit;
- /** Specification; used for toParseableString(). */
- private final String specification;
-
- private CacheBuilderSpec(String specification) {
- this.specification = specification;
- }
-
- /**
- * Creates a CacheBuilderSpec from a string.
- *
- * @param cacheBuilderSpecification the string form
- */
- public static CacheBuilderSpec parse(String cacheBuilderSpecification) {
- CacheBuilderSpec spec = new CacheBuilderSpec(cacheBuilderSpecification);
- if (!cacheBuilderSpecification.isEmpty()) {
- for (String keyValuePair : KEYS_SPLITTER.split(cacheBuilderSpecification)) {
- List<String> keyAndValue = ImmutableList.copyOf(KEY_VALUE_SPLITTER.split(keyValuePair));
- checkArgument(!keyAndValue.isEmpty(), "blank key-value pair");
- checkArgument(keyAndValue.size() <= 2,
- "key-value pair %s with more than one equals sign", keyValuePair);
-
- // Find the ValueParser for the current key.
- String key = keyAndValue.get(0);
- ValueParser valueParser = VALUE_PARSERS.get(key);
- checkArgument(valueParser != null, "unknown key %s", key);
-
- String value = keyAndValue.size() == 1 ? null : keyAndValue.get(1);
- valueParser.parse(spec, key, value);
- }
- }
-
- return spec;
- }
-
- /**
- * Returns a CacheBuilderSpec that will prevent caching.
- */
- public static CacheBuilderSpec disableCaching() {
- // Maximum size of zero is one way to block caching
- return CacheBuilderSpec.parse("maximumSize=0");
- }
-
- /**
- * Returns a CacheBuilder configured according to this instance's specification.
- */
- CacheBuilder<Object, Object> toCacheBuilder() {
- CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
- if (initialCapacity != null) {
- builder.initialCapacity(initialCapacity);
- }
- if (maximumSize != null) {
- builder.maximumSize(maximumSize);
- }
- if (maximumWeight != null) {
- builder.maximumWeight(maximumWeight);
- }
- if (concurrencyLevel != null) {
- builder.concurrencyLevel(concurrencyLevel);
- }
- if (keyStrength != null) {
- switch (keyStrength) {
- case WEAK:
- builder.weakKeys();
- break;
- default:
- throw new AssertionError();
- }
- }
- if (valueStrength != null) {
- switch (valueStrength) {
- case SOFT:
- builder.softValues();
- break;
- case WEAK:
- builder.weakValues();
- break;
- default:
- throw new AssertionError();
- }
- }
- if (writeExpirationTimeUnit != null) {
- builder.expireAfterWrite(writeExpirationDuration, writeExpirationTimeUnit);
- }
- if (accessExpirationTimeUnit != null) {
- builder.expireAfterAccess(accessExpirationDuration, accessExpirationTimeUnit);
- }
- if (refreshTimeUnit != null) {
- builder.refreshAfterWrite(refreshDuration, refreshTimeUnit);
- }
-
- return builder;
- }
-
- /**
- * Returns a string that can be used to parse an equivalent
- * {@code CacheBuilderSpec}. The order and form of this representation is
- * not guaranteed, except that reparsing its output will produce
- * a {@code CacheBuilderSpec} equal to this instance.
- */
- public String toParsableString() {
- return specification;
- }
-
- /**
- * Returns a string representation for this CacheBuilderSpec instance.
- * The form of this representation is not guaranteed.
- */
- @Override
- public String toString() {
- return Objects.toStringHelper(this).addValue(toParsableString()).toString();
- }
-
- @Override
- public int hashCode() {
- return Objects.hashCode(
- initialCapacity,
- maximumSize,
- maximumWeight,
- concurrencyLevel,
- keyStrength,
- valueStrength,
- durationInNanos(writeExpirationDuration, writeExpirationTimeUnit),
- durationInNanos(accessExpirationDuration, accessExpirationTimeUnit),
- durationInNanos(refreshDuration, refreshTimeUnit));
- }
-
- @Override
- public boolean equals(@Nullable Object obj) {
- if (this == obj) {
- return true;
- }
- if (!(obj instanceof CacheBuilderSpec)) {
- return false;
- }
- CacheBuilderSpec that = (CacheBuilderSpec) obj;
- return Objects.equal(initialCapacity, that.initialCapacity)
- && Objects.equal(maximumSize, that.maximumSize)
- && Objects.equal(maximumWeight, that.maximumWeight)
- && Objects.equal(concurrencyLevel, that.concurrencyLevel)
- && Objects.equal(keyStrength, that.keyStrength)
- && Objects.equal(valueStrength, that.valueStrength)
- && Objects.equal(durationInNanos(writeExpirationDuration, writeExpirationTimeUnit),
- durationInNanos(that.writeExpirationDuration, that.writeExpirationTimeUnit))
- && Objects.equal(durationInNanos(accessExpirationDuration, accessExpirationTimeUnit),
- durationInNanos(that.accessExpirationDuration, that.accessExpirationTimeUnit))
- && Objects.equal(durationInNanos(refreshDuration, refreshTimeUnit),
- durationInNanos(that.refreshDuration, that.refreshTimeUnit));
- }
-
- /**
- * Converts an expiration duration/unit pair into a single Long for hashing and equality.
- * Uses nanos to match CacheBuilder implementation.
- */
- @Nullable private static Long durationInNanos(long duration, @Nullable TimeUnit unit) {
- return (unit == null) ? null : unit.toNanos(duration);
- }
-
- /** Base class for parsing integers. */
- abstract static class IntegerParser implements ValueParser {
- protected abstract void parseInteger(CacheBuilderSpec spec, int value);
-
- @Override
- public void parse(CacheBuilderSpec spec, String key, String value) {
- checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
- try {
- parseInteger(spec, Integer.parseInt(value));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException(
- String.format("key %s value set to %s, must be integer", key, value), e);
- }
- }
- }
-
- /** Base class for parsing integers. */
- abstract static class LongParser implements ValueParser {
- protected abstract void parseLong(CacheBuilderSpec spec, long value);
-
- @Override
- public void parse(CacheBuilderSpec spec, String key, String value) {
- checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
- try {
- parseLong(spec, Long.parseLong(value));
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException(
- String.format("key %s value set to %s, must be integer", key, value), e);
- }
- }
- }
-
- /** Parse initialCapacity */
- static class InitialCapacityParser extends IntegerParser {
- @Override
- protected void parseInteger(CacheBuilderSpec spec, int value) {
- checkArgument(spec.initialCapacity == null,
- "initial capacity was already set to ", spec.initialCapacity);
- spec.initialCapacity = value;
- }
- }
-
- /** Parse maximumSize */
- static class MaximumSizeParser extends LongParser {
- @Override
- protected void parseLong(CacheBuilderSpec spec, long value) {
- checkArgument(spec.maximumSize == null,
- "maximum size was already set to ", spec.maximumSize);
- checkArgument(spec.maximumWeight == null,
- "maximum weight was already set to ", spec.maximumWeight);
- spec.maximumSize = value;
- }
- }
-
- /** Parse maximumWeight */
- static class MaximumWeightParser extends LongParser {
- @Override
- protected void parseLong(CacheBuilderSpec spec, long value) {
- checkArgument(spec.maximumWeight == null,
- "maximum weight was already set to ", spec.maximumWeight);
- checkArgument(spec.maximumSize == null,
- "maximum size was already set to ", spec.maximumSize);
- spec.maximumWeight = value;
- }
- }
-
- /** Parse concurrencyLevel */
- static class ConcurrencyLevelParser extends IntegerParser {
- @Override
- protected void parseInteger(CacheBuilderSpec spec, int value) {
- checkArgument(spec.concurrencyLevel == null,
- "concurrency level was already set to ", spec.concurrencyLevel);
- spec.concurrencyLevel = value;
- }
- }
-
- /** Parse weakKeys */
- static class KeyStrengthParser implements ValueParser {
- private final Strength strength;
-
- public KeyStrengthParser(Strength strength) {
- this.strength = strength;
- }
-
- @Override
- public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
- checkArgument(value == null, "key %s does not take values", key);
- checkArgument(spec.keyStrength == null, "%s was already set to %s", key, spec.keyStrength);
- spec.keyStrength = strength;
- }
- }
-
- /** Parse weakValues and softValues */
- static class ValueStrengthParser implements ValueParser {
- private final Strength strength;
-
- public ValueStrengthParser(Strength strength) {
- this.strength = strength;
- }
-
- @Override
- public void parse(CacheBuilderSpec spec, String key, @Nullable String value) {
- checkArgument(value == null, "key %s does not take values", key);
- checkArgument(spec.valueStrength == null,
- "%s was already set to %s", key, spec.valueStrength);
-
- spec.valueStrength = strength;
- }
- }
-
- /** Base class for parsing times with durations */
- abstract static class DurationParser implements ValueParser {
- protected abstract void parseDuration(
- CacheBuilderSpec spec,
- long duration,
- TimeUnit unit);
-
- @Override
- public void parse(CacheBuilderSpec spec, String key, String value) {
- checkArgument(value != null && !value.isEmpty(), "value of key %s omitted", key);
- try {
- char lastChar = value.charAt(value.length() - 1);
- TimeUnit timeUnit;
- switch (lastChar) {
- case 'd':
- timeUnit = TimeUnit.DAYS;
- break;
- case 'h':
- timeUnit = TimeUnit.HOURS;
- break;
- case 'm':
- timeUnit = TimeUnit.MINUTES;
- break;
- case 's':
- timeUnit = TimeUnit.SECONDS;
- break;
- default:
- throw new IllegalArgumentException(
- String.format("key %s invalid format. was %s, must end with one of [dDhHmMsS]",
- key, value));
- }
-
- long duration = Long.parseLong(value.substring(0, value.length() - 1));
- parseDuration(spec, duration, timeUnit);
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException(
- String.format("key %s value set to %s, must be integer", key, value));
- }
- }
- }
-
- /** Parse expireAfterAccess */
- static class AccessDurationParser extends DurationParser {
- @Override protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
- checkArgument(spec.accessExpirationTimeUnit == null, "expireAfterAccess already set");
- spec.accessExpirationDuration = duration;
- spec.accessExpirationTimeUnit = unit;
- }
- }
-
- /** Parse expireAfterWrite */
- static class WriteDurationParser extends DurationParser {
- @Override protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
- checkArgument(spec.writeExpirationTimeUnit == null, "expireAfterWrite already set");
- spec.writeExpirationDuration = duration;
- spec.writeExpirationTimeUnit = unit;
- }
- }
-
- /** Parse refreshAfterWrite */
- static class RefreshDurationParser extends DurationParser {
- @Override protected void parseDuration(CacheBuilderSpec spec, long duration, TimeUnit unit) {
- checkArgument(spec.refreshTimeUnit == null, "refreshAfterWrite already set");
- spec.refreshDuration = duration;
- spec.refreshTimeUnit = unit;
- }
- }
-}
diff --git a/guava/src/com/google/common/cache/CacheLoader.java b/guava/src/com/google/common/cache/CacheLoader.java
index 2f014a3..21811e8 100644
--- a/guava/src/com/google/common/cache/CacheLoader.java
+++ b/guava/src/com/google/common/cache/CacheLoader.java
@@ -30,23 +30,15 @@ import java.io.Serializable;
import java.util.Map;
/**
- * Computes or retrieves values, based on a key, for use in populating a {@link LoadingCache}.
+ * Computes or retrieves values, based on a key, for use in populating a {@code Cache}.
*
* <p>Most implementations will only need to implement {@link #load}. Other methods may be
* overridden as desired.
*
- * <p>Usage example: <pre> {@code
- *
- * CacheLoader<Key, Graph> loader = new CacheLoader<Key, Graph>() {
- * public Graph load(Key key) throws AnyException {
- * return createExpensiveGraph(key);
- * }
- * };
- * LoadingCache<Key, Graph> cache = CacheBuilder.newBuilder().build(loader);}</pre>
- *
* @author Charles Fry
* @since 10.0
*/
+@Beta
@GwtCompatible(emulated = true)
public abstract class CacheLoader<K, V> {
/**
@@ -59,17 +51,13 @@ public abstract class CacheLoader<K, V> {
*
* @param key the non-null key whose value should be loaded
* @return the value associated with {@code key}; <b>must not be null</b>
- * @throws Exception if unable to load the result
- * @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
- * treated like any other {@code Exception} in all respects except that, when it is caught,
- * the thread's interrupt status is set
*/
public abstract V load(K key) throws Exception;
/**
* Computes or retrieves a replacement value corresponding to an already-cached {@code key}. This
* method is called when an existing cache entry is refreshed by
- * {@link CacheBuilder#refreshAfterWrite}, or through a call to {@link LoadingCache#refresh}.
+ * {@link CacheBuilder#refreshAfterWrite}, or through a call to {@link Cache#refresh}.
*
* <p>This implementation synchronously delegates to {@link #load}. It is recommended that it be
* overridden with an asynchronous implementation when using
@@ -81,22 +69,16 @@ public abstract class CacheLoader<K, V> {
* @param oldValue the non-null old value corresponding to {@code key}
* @return the future new value associated with {@code key};
* <b>must not be null, must not return null</b>
- * @throws Exception if unable to reload the result
- * @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
- * treated like any other {@code Exception} in all respects except that, when it is caught,
- * the thread's interrupt status is set
* @since 11.0
*/
@GwtIncompatible("Futures")
public ListenableFuture<V> reload(K key, V oldValue) throws Exception {
- checkNotNull(key);
- checkNotNull(oldValue);
return Futures.immediateFuture(load(key));
}
/**
* Computes or retrieves the values corresponding to {@code keys}. This method is called by
- * {@link LoadingCache#getAll}.
+ * {@link Cache#getAll}.
*
* <p>If the returned map doesn't contain all requested {@code keys} then the entries it does
* contain will be cached, but {@code getAll} will throw an exception. If the returned map
@@ -104,33 +86,22 @@ public abstract class CacheLoader<K, V> {
* but only the entries for {@code keys} will be returned from {@code getAll}.
*
* <p>This method should be overriden when bulk retrieval is significantly more efficient than
- * many individual lookups. Note that {@link LoadingCache#getAll} will defer to individual calls
- * to {@link LoadingCache#get} if this method is not overriden.
+ * many individual lookups. Note that {@link Cache#getAll} will defer to individual calls to
+ * {@link Cache#get} if this method is not overriden.
*
* @param keys the unique, non-null keys whose values should be loaded
* @return a map from each key in {@code keys} to the value associated with that key;
* <b>may not contain null values</b>
- * @throws Exception if unable to load the result
- * @throws InterruptedException if this method is interrupted. {@code InterruptedException} is
- * treated like any other {@code Exception} in all respects except that, when it is caught,
- * the thread's interrupt status is set
* @since 11.0
*/
public Map<K, V> loadAll(Iterable<? extends K> keys) throws Exception {
- // This will be caught by getAll(), causing it to fall back to multiple calls to
- // LoadingCache.get
+ // This will be caught by getAll(), causing it to fall back to multiple calls to Cache.get
throw new UnsupportedLoadingOperationException();
}
/**
- * Returns a cache loader based on an <i>existing</i> function instance. Note that there's no need
- * to create a <i>new</i> function just to pass it in here; just subclass {@code CacheLoader} and
- * implement {@link #load load} instead.
- *
- * @param function the function to be used for loading values; must never return {@code null}
- * @return a cache loader that loads values by passing each key to {@code function}
+ * Returns a {@code CacheLoader} which creates values by applying a {@code Function} to the key.
*/
- @Beta
public static <K, V> CacheLoader<K, V> from(Function<K, V> function) {
return new FunctionToCacheLoader<K, V>(function);
}
@@ -145,22 +116,16 @@ public abstract class CacheLoader<K, V> {
@Override
public V load(K key) {
- return computingFunction.apply(checkNotNull(key));
+ return computingFunction.apply(key);
}
private static final long serialVersionUID = 0;
}
/**
- * Returns a cache loader based on an <i>existing</i> supplier instance. Note that there's no need
- * to create a <i>new</i> supplier just to pass it in here; just subclass {@code CacheLoader} and
- * implement {@link #load load} instead.
- *
- * @param supplier the supplier to be used for loading values; must never return {@code null}
- * @return a cache loader that loads values by calling {@link Supplier#get}, irrespective of the
- * key
+ * Returns a {@code CacheLoader} which obtains values from a {@code Supplier} (independent of the
+ * key).
*/
- @Beta
public static <V> CacheLoader<Object, V> from(Supplier<V> supplier) {
return new SupplierToCacheLoader<V>(supplier);
}
@@ -175,7 +140,6 @@ public abstract class CacheLoader<K, V> {
@Override
public V load(Object key) {
- checkNotNull(key);
return computingSupplier.get();
}
diff --git a/guava/src/com/google/common/cache/CacheStats.java b/guava/src/com/google/common/cache/CacheStats.java
index d8c9eb7..04d442c 100644
--- a/guava/src/com/google/common/cache/CacheStats.java
+++ b/guava/src/com/google/common/cache/CacheStats.java
@@ -22,8 +22,6 @@ import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
-import java.util.concurrent.Callable;
-
import javax.annotation.Nullable;
/**
@@ -46,14 +44,9 @@ import javax.annotation.Nullable;
* </ul>
* <li>When an entry is evicted from the cache, {@code evictionCount} is incremented.
* <li>No stats are modified when a cache entry is invalidated or manually removed.
- * <li>No stats are modified on a query to {@link Cache#getIfPresent}.
* <li>No stats are modified by operations invoked on the {@linkplain Cache#asMap asMap} view of
* the cache.
* </ul>
- *
- * <p>A lookup is specifically defined as an invocation of one of the methods
- * {@link LoadingCache#get(Object)}, {@link LoadingCache#getUnchecked(Object)},
- * {@link Cache#get(Object, Callable)}, or {@link LoadingCache#getAll(Iterable)}.
*
* @author Charles Fry
* @since 10.0
diff --git a/guava/src/com/google/common/cache/ForwardingCache.java b/guava/src/com/google/common/cache/ForwardingCache.java
index 44fe683..4404593 100644
--- a/guava/src/com/google/common/cache/ForwardingCache.java
+++ b/guava/src/com/google/common/cache/ForwardingCache.java
@@ -21,7 +21,6 @@ import com.google.common.base.Preconditions;
import com.google.common.collect.ForwardingObject;
import com.google.common.collect.ImmutableMap;
-import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
@@ -50,7 +49,7 @@ public abstract class ForwardingCache<K, V> extends ForwardingObject implements
*/
@Override
@Nullable
- public V getIfPresent(Object key) {
+ public V getIfPresent(K key) {
return delegate().getIfPresent(key);
}
@@ -66,7 +65,7 @@ public abstract class ForwardingCache<K, V> extends ForwardingObject implements
* @since 11.0
*/
@Override
- public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
+ public ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys) {
return delegate().getAllPresent(keys);
}
@@ -78,14 +77,6 @@ public abstract class ForwardingCache<K, V> extends ForwardingObject implements
delegate().put(key, value);
}
- /**
- * @since 12.0
- */
- @Override
- public void putAll(Map<? extends K,? extends V> m) {
- delegate().putAll(m);
- }
-
@Override
public void invalidate(Object key) {
delegate().invalidate(key);
@@ -124,6 +115,24 @@ public abstract class ForwardingCache<K, V> extends ForwardingObject implements
delegate().cleanUp();
}
+ @Deprecated
+ @Override
+ public V get(K key) throws ExecutionException {
+ return delegate().get(key);
+ }
+
+ @Deprecated
+ @Override
+ public V getUnchecked(K key) {
+ return delegate().getUnchecked(key);
+ }
+
+ @Deprecated
+ @Override
+ public V apply(K key) {
+ return delegate().apply(key);
+ }
+
/**
* A simplified version of {@link ForwardingCache} where subclasses can pass in an already
* constructed {@link Cache} as the delegete.
diff --git a/guava/src/com/google/common/cache/LoadingCache.java b/guava/src/com/google/common/cache/LoadingCache.java
index 05b1312..471c31a 100644
--- a/guava/src/com/google/common/cache/LoadingCache.java
+++ b/guava/src/com/google/common/cache/LoadingCache.java
@@ -33,14 +33,11 @@ import java.util.concurrent.ExecutionException;
* <p>Implementations of this interface are expected to be thread-safe, and can be safely accessed
* by multiple concurrent threads.
*
+ * <p>All methods other than {@link #get} and {@link #getUnchecked} are optional.
+ *
* <p>When evaluated as a {@link Function}, a cache yields the same result as invoking
* {@link #getUnchecked}.
*
- * <p>Note that while this class is still annotated as {@link Beta}, the API is frozen from a
- * consumer's standpoint. In other words existing methods are all considered {@code non-Beta} and
- * won't be changed without going through an 18 month deprecation cycle; however new methods may be
- * added at any time.
- *
* @author Charles Fry
* @since 11.0
*/
@@ -141,8 +138,6 @@ public interface LoadingCache<K, V> extends Cache<K, V>, Function<K, V> {
*
* <p>Caches loaded by a {@link CacheLoader} will call {@link CacheLoader#reload} if the
* cache currently contains a value for {@code key}, and {@link CacheLoader#load} otherwise.
- * Loading is asynchronous only if {@link CacheLoader#reload} was overridden with an
- * asynchronous implementation.
*
* <p>Returns without doing anything if another thread is currently loading the value for
* {@code key}. If the cache loader associated with this cache performs refresh asynchronously
diff --git a/guava/src/com/google/common/cache/LocalCache.java b/guava/src/com/google/common/cache/LocalCache.java
index d7c5bd7..4973429 100644
--- a/guava/src/com/google/common/cache/LocalCache.java
+++ b/guava/src/com/google/common/cache/LocalCache.java
@@ -23,10 +23,9 @@ import static com.google.common.cache.CacheBuilder.UNSET_INT;
import static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import com.google.common.annotations.GwtCompatible;
-import com.google.common.annotations.GwtIncompatible;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Equivalence;
+import com.google.common.base.Equivalences;
import com.google.common.base.Stopwatch;
import com.google.common.base.Ticker;
import com.google.common.cache.AbstractCache.SimpleStatsCounter;
@@ -35,7 +34,7 @@ import com.google.common.cache.CacheBuilder.NullListener;
import com.google.common.cache.CacheBuilder.OneWeigher;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.cache.CacheLoader.UnsupportedLoadingOperationException;
-import com.google.common.collect.AbstractSequentialIterator;
+import com.google.common.collect.AbstractLinkedIterator;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterators;
import com.google.common.collect.Maps;
@@ -48,7 +47,6 @@ import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
import com.google.common.util.concurrent.UncheckedExecutionException;
-import com.google.common.util.concurrent.Uninterruptibles;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -57,6 +55,7 @@ import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
+import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractQueue;
import java.util.AbstractSet;
@@ -90,7 +89,6 @@ import javax.annotation.concurrent.GuardedBy;
* @author Bob Lee ({@code com.google.common.collect.MapMaker})
* @author Doug Lea ({@code ConcurrentHashMap})
*/
-@GwtCompatible(emulated = true)
class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> {
/*
@@ -232,8 +230,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
/**
* Creates a new, empty map with the specified strategy, initial capacity and concurrency level.
*/
- LocalCache(
- CacheBuilder<? super K, ? super V> builder, @Nullable CacheLoader<? super K, V> loader) {
+ LocalCache(CacheBuilder<? super K, ? super V> builder, CacheLoader<? super K, V> loader) {
concurrencyLevel = Math.min(builder.getConcurrencyLevel(), MAX_SEGMENTS);
keyStrength = builder.getKeyStrength();
@@ -263,15 +260,13 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
initialCapacity = Math.min(initialCapacity, (int) maxWeight);
}
- // Find the lowest power-of-two segmentCount that exceeds concurrencyLevel, unless
- // maximumSize/Weight is specified in which case ensure that each segment gets at least 10
- // entries. The special casing for size-based eviction is only necessary because that eviction
- // happens per segment instead of globally, so too many segments compared to the maximum size
- // will result in random eviction behavior.
+ // Find power-of-two sizes best matching arguments. Constraints:
+ // (segmentCount <= maxWeight)
+ // && (concurrencyLevel > maxWeight || segmentCount > concurrencyLevel)
int segmentShift = 0;
int segmentCount = 1;
while (segmentCount < concurrencyLevel
- && (!evictsBySize() || segmentCount * 20 <= maxWeight)) {
+ && (!evictsBySize() || customWeigher() || segmentCount * 2 <= maxWeight)) {
++segmentShift;
segmentCount <<= 1;
}
@@ -386,7 +381,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
Equivalence<Object> defaultEquivalence() {
- return Equivalence.equals();
+ return Equivalences.equals();
}
},
@@ -402,7 +397,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
Equivalence<Object> defaultEquivalence() {
- return Equivalence.identity();
+ return Equivalences.identity();
}
},
@@ -418,7 +413,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
Equivalence<Object> defaultEquivalence() {
- return Equivalence.identity();
+ return Equivalences.identity();
}
};
@@ -652,11 +647,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
/**
* Creates a copy of this reference for the given entry.
- *
- * <p>{@code value} may be null only for a loading reference.
*/
- ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, @Nullable V value, ReferenceEntry<K, V> entry);
+ ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry);
/**
* Notifify pending loads that a new value was set. This is only relevant to loading
@@ -701,8 +693,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
@Override
- public ValueReference<Object, Object> copyFor(ReferenceQueue<Object> queue,
- @Nullable Object value, ReferenceEntry<Object, Object> entry) {
+ public ValueReference<Object, Object> copyFor(
+ ReferenceQueue<Object> queue, ReferenceEntry<Object, Object> entry) {
return this;
}
@@ -1664,8 +1656,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
public ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, V value, ReferenceEntry<K, V> entry) {
- return new WeakValueReference<K, V>(queue, value, entry);
+ ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
+ return new WeakValueReference<K, V>(queue, get(), entry);
}
@Override
@@ -1710,9 +1702,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
public void notifyNewValue(V newValue) {}
@Override
- public ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, V value, ReferenceEntry<K, V> entry) {
- return new SoftValueReference<K, V>(queue, value, entry);
+ public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
+ return new SoftValueReference<K, V>(queue, get(), entry);
}
@Override
@@ -1757,8 +1748,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
@Override
- public ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, V value, ReferenceEntry<K, V> entry) {
+ public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
return this;
}
@@ -1800,8 +1790,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
public ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, V value, ReferenceEntry<K, V> entry) {
- return new WeightedWeakValueReference<K, V>(queue, value, entry, weight);
+ ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
+ return new WeightedWeakValueReference<K, V>(queue, get(), entry, weight);
}
}
@@ -1822,9 +1812,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
return weight;
}
@Override
- public ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, V value, ReferenceEntry<K, V> entry) {
- return new WeightedSoftValueReference<K, V>(queue, value, entry, weight);
+ public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
+ return new WeightedSoftValueReference<K, V>(queue, get(), entry, weight);
}
}
@@ -1892,10 +1881,10 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@VisibleForTesting
ValueReference<K, V> newValueReference(ReferenceEntry<K, V> entry, V value, int weight) {
int hash = entry.getHash();
- return valueStrength.referenceValue(segmentFor(hash), entry, checkNotNull(value), weight);
+ return valueStrength.referenceValue(segmentFor(hash), entry, value, weight);
}
- int hash(@Nullable Object key) {
+ int hash(Object key) {
int h = keyEquivalence.hash(key);
return rehash(h);
}
@@ -1964,13 +1953,12 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
* Returns true if the entry has expired.
*/
boolean isExpired(ReferenceEntry<K, V> entry, long now) {
- checkNotNull(entry);
if (expiresAfterAccess()
- && (now - entry.getAccessTime() >= expireAfterAccessNanos)) {
+ && (now - entry.getAccessTime() > expireAfterAccessNanos)) {
return true;
}
if (expiresAfterWrite()
- && (now - entry.getWriteTime() >= expireAfterWriteNanos)) {
+ && (now - entry.getWriteTime() > expireAfterWriteNanos)) {
return true;
}
return false;
@@ -2150,7 +2138,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
StatsCounter statsCounter) {
this.map = map;
this.maxSegmentWeight = maxSegmentWeight;
- this.statsCounter = checkNotNull(statsCounter);
+ this.statsCounter = statsCounter;
initTable(newEntryArray(initialCapacity));
keyReferenceQueue = map.usesKeyReferences()
@@ -2187,29 +2175,14 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@GuardedBy("Segment.this")
ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
- return map.entryFactory.newEntry(this, checkNotNull(key), hash, next);
+ return map.entryFactory.newEntry(this, key, hash, next);
}
- /**
- * 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.
- */
@GuardedBy("Segment.this")
ReferenceEntry<K, V> copyEntry(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));
+ newEntry.setValueReference(valueReference.copyFor(this.valueReferenceQueue, newEntry));
return newEntry;
}
@@ -2232,8 +2205,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
// loading
V get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {
- checkNotNull(key);
- checkNotNull(loader);
try {
if (count != 0) { // read-volatile
// don't call getLiveEntry, which would ignore loading values
@@ -2424,9 +2395,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
V scheduleRefresh(ReferenceEntry<K, V> entry, K key, int hash, V oldValue, long now,
CacheLoader<? super K, V> loader) {
- if (map.refreshes() && (now - entry.getWriteTime() > map.refreshNanos)
- && !entry.getValueReference().isLoading()) {
- V newValue = refresh(key, hash, loader, true);
+ if (map.refreshes() && (now - entry.getWriteTime() > map.refreshNanos)) {
+ V newValue = refresh(key, hash, loader);
if (newValue != null) {
return newValue;
}
@@ -2441,9 +2411,9 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
* refresh.
*/
@Nullable
- V refresh(K key, int hash, CacheLoader<? super K, V> loader, boolean checkTime) {
+ V refresh(K key, int hash, CacheLoader<? super K, V> loader) {
final LoadingValueReference<K, V> loadingValueReference =
- insertLoadingValueReference(key, hash, checkTime);
+ insertLoadingValueReference(key, hash);
if (loadingValueReference == null) {
return null;
}
@@ -2451,7 +2421,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
ListenableFuture<V> result = loadAsync(key, hash, loadingValueReference, loader);
if (result.isDone()) {
try {
- return Uninterruptibles.getUninterruptibly(result);
+ return result.get();
} catch (Throwable t) {
// don't let refresh exceptions propagate; error was already logged
}
@@ -2464,8 +2434,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
* is already loading.
*/
@Nullable
- LoadingValueReference<K, V> insertLoadingValueReference(final K key, final int hash,
- boolean checkTime) {
+ LoadingValueReference<K, V> insertLoadingValueReference(final K key, final int hash) {
ReferenceEntry<K, V> e = null;
lock();
try {
@@ -2484,11 +2453,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
// We found an existing entry.
ValueReference<K, V> valueReference = e.getValueReference();
- if (valueReference.isLoading()
- || (checkTime && (now - e.getWriteTime() < map.refreshNanos))) {
+ if (valueReference.isLoading()) {
// refresh is a no-op if loading is pending
- // if checkTime, we want to check *after* acquiring the lock if refresh still needs
- // to be scheduled
return null;
}
@@ -3008,14 +2974,14 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
// Clone nodes leading up to the tail.
for (ReferenceEntry<K, V> e = head; e != tail; e = e.getNext()) {
- int newIndex = e.getHash() & newMask;
- ReferenceEntry<K, V> newNext = newTable.get(newIndex);
- ReferenceEntry<K, V> newFirst = copyEntry(e, newNext);
- if (newFirst != null) {
- newTable.set(newIndex, newFirst);
- } else {
+ if (isCollected(e)) {
removeCollectedEntry(e);
newCount--;
+ } else {
+ int newIndex = e.getHash() & newMask;
+ ReferenceEntry<K, V> newNext = newTable.get(newIndex);
+ ReferenceEntry<K, V> newFirst = copyEntry(e, newNext);
+ newTable.set(newIndex, newFirst);
}
}
}
@@ -3177,11 +3143,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
preWriteCleanup(now);
int newCount = this.count + 1;
- if (newCount > this.threshold) { // ensure capacity
- expand();
- newCount = this.count + 1;
- }
-
AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
int index = hash & (table.length() - 1);
ReferenceEntry<K, V> first = table.get(index);
@@ -3192,10 +3153,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
&& map.keyEquivalence.equivalent(key, entryKey)) {
ValueReference<K, V> valueReference = e.getValueReference();
V entryValue = valueReference.get();
- // replace the old LoadingValueReference if it's live, otherwise
- // perform a putIfAbsent
- if (oldValueReference == valueReference
- || (entryValue == null && valueReference != UNSET)) {
+ if (entryValue == null || oldValueReference == valueReference) {
++modCount;
if (oldValueReference.isActive()) {
RemovalCause cause =
@@ -3328,12 +3286,11 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
int newCount = count;
ReferenceEntry<K, V> newFirst = entry.getNext();
for (ReferenceEntry<K, V> e = first; e != entry; e = e.getNext()) {
- ReferenceEntry<K, V> next = copyEntry(e, newFirst);
- if (next != null) {
- newFirst = next;
- } else {
+ if (isCollected(e)) {
removeCollectedEntry(e);
newCount--;
+ } else {
+ newFirst = copyEntry(e, newFirst);
}
}
this.count = newCount;
@@ -3470,6 +3427,18 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
/**
+ * Returns true if the entry has been partially collected, meaning that either the key is null,
+ * or the value is active but null.
+ */
+ boolean isCollected(ReferenceEntry<K, V> entry) {
+ if (entry.getKey() == null) {
+ return true;
+ }
+ ValueReference<K, V> valueReference = entry.getValueReference();
+ return (valueReference.get() == null) && valueReference.isActive();
+ }
+
+ /**
* Performs routine cleanup following a read. Normally cleanup happens during writes. If cleanup
* is not observed after a sufficient number of reads, try cleaning up from the read thread.
*/
@@ -3604,15 +3573,12 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
return newValue != null ? newValue : Futures.<V>immediateFuture(null);
}
} catch (Throwable t) {
- if (t instanceof InterruptedException) {
- Thread.currentThread().interrupt();
- }
return setException(t) ? futureValue : fullyFailedFuture(t);
}
}
public long elapsedNanos() {
- return stopwatch.elapsed(NANOSECONDS);
+ return stopwatch.elapsedTime(NANOSECONDS);
}
@Override
@@ -3635,8 +3601,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
@Override
- public ValueReference<K, V> copyFor(
- ReferenceQueue<V> queue, @Nullable V value, ReferenceEntry<K, V> entry) {
+ public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
return this;
}
}
@@ -3770,7 +3735,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
public Iterator<ReferenceEntry<K, V>> iterator() {
- return new AbstractSequentialIterator<ReferenceEntry<K, V>>(peek()) {
+ return new AbstractLinkedIterator<ReferenceEntry<K, V>>(peek()) {
@Override
protected ReferenceEntry<K, V> computeNext(ReferenceEntry<K, V> previous) {
ReferenceEntry<K, V> next = previous.getNextInWriteQueue();
@@ -3907,7 +3872,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Override
public Iterator<ReferenceEntry<K, V>> iterator() {
- return new AbstractSequentialIterator<ReferenceEntry<K, V>>(peek()) {
+ return new AbstractLinkedIterator<ReferenceEntry<K, V>>(peek()) {
@Override
protected ReferenceEntry<K, V> computeNext(ReferenceEntry<K, V> previous) {
ReferenceEntry<K, V> next = previous.getNextInAccessQueue();
@@ -4004,20 +3969,17 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
return get(key, defaultLoader);
}
- ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
+ ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys) {
int hits = 0;
int misses = 0;
Map<K, V> result = Maps.newLinkedHashMap();
- for (Object key : keys) {
+ for (K key : keys) {
V value = get(key);
if (value == null) {
misses++;
} else {
- // TODO(fry): store entry key instead of query key
- @SuppressWarnings("unchecked")
- K castKey = (K) key;
- result.put(castKey, value);
+ result.put(key, value);
hits++;
}
}
@@ -4026,7 +3988,8 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
return ImmutableMap.copyOf(result);
}
- ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
+ ImmutableMap<K, V> getAll(Iterable<? extends K> keys)
+ throws ExecutionException {
int hits = 0;
int misses = 0;
@@ -4078,8 +4041,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
@Nullable
Map<K, V> loadAll(Set<? extends K> keys, CacheLoader<? super K, V> loader)
throws ExecutionException {
- checkNotNull(loader);
- checkNotNull(keys);
Stopwatch stopwatch = new Stopwatch().start();
Map<K, V> result;
boolean success = false;
@@ -4091,9 +4052,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
} catch (UnsupportedLoadingOperationException e) {
success = true;
throw e;
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new ExecutionException(e);
} catch (RuntimeException e) {
throw new UncheckedExecutionException(e);
} catch (Exception e) {
@@ -4102,12 +4060,12 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
throw new ExecutionError(e);
} finally {
if (!success) {
- globalStatsCounter.recordLoadException(stopwatch.elapsed(NANOSECONDS));
+ globalStatsCounter.recordLoadException(stopwatch.elapsedTime(NANOSECONDS));
}
}
if (result == null) {
- globalStatsCounter.recordLoadException(stopwatch.elapsed(NANOSECONDS));
+ globalStatsCounter.recordLoadException(stopwatch.elapsedTime(NANOSECONDS));
throw new InvalidCacheLoadException(loader + " returned null map from loadAll");
}
@@ -4126,12 +4084,12 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
if (nullsPresent) {
- globalStatsCounter.recordLoadException(stopwatch.elapsed(NANOSECONDS));
+ globalStatsCounter.recordLoadException(stopwatch.elapsedTime(NANOSECONDS));
throw new InvalidCacheLoadException(loader + " returned null keys or values from loadAll");
}
// TODO(fry): record count of loaded entries
- globalStatsCounter.recordLoadSuccess(stopwatch.elapsed(NANOSECONDS));
+ globalStatsCounter.recordLoadSuccess(stopwatch.elapsedTime(NANOSECONDS));
return result;
}
@@ -4148,9 +4106,21 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
return segmentFor(hash).getEntry(key, hash);
}
+ /**
+ * Returns the live internal entry for the specified key.
+ */
+ ReferenceEntry<K, V> getLiveEntry(@Nullable Object key) {
+ // does not impact recency ordering
+ if (key == null) {
+ return null;
+ }
+ int hash = hash(key);
+ return segmentFor(hash).getLiveEntry(key, hash, ticker.read());
+ }
+
void refresh(K key) {
int hash = hash(checkNotNull(key));
- segmentFor(hash).refresh(key, hash, defaultLoader, false);
+ segmentFor(hash).refresh(key, hash, defaultLoader);
}
@Override
@@ -4284,7 +4254,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
public Set<K> keySet() {
// does not impact recency ordering
Set<K> ks = keySet;
- return (ks != null) ? ks : (keySet = new KeySet(this));
+ return (ks != null) ? ks : (keySet = new KeySet());
}
Collection<V> values;
@@ -4293,22 +4263,21 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
public Collection<V> values() {
// does not impact recency ordering
Collection<V> vs = values;
- return (vs != null) ? vs : (values = new Values(this));
+ return (vs != null) ? vs : (values = new Values());
}
Set<Entry<K, V>> entrySet;
@Override
- @GwtIncompatible("Not supported.")
public Set<Entry<K, V>> entrySet() {
// does not impact recency ordering
Set<Entry<K, V>> es = entrySet;
- return (es != null) ? es : (entrySet = new EntrySet(this));
+ return (es != null) ? es : (entrySet = new EntrySet());
}
// Iterator Support
- abstract class HashIterator<T> implements Iterator<T> {
+ abstract class HashIterator {
int nextSegmentIndex;
int nextTableIndex;
@@ -4324,9 +4293,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
advance();
}
- @Override
- public abstract T next();
-
final void advance() {
nextExternal = null;
@@ -4399,7 +4365,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
}
- @Override
public boolean hasNext() {
return nextExternal != null;
}
@@ -4413,7 +4378,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
return lastReturned;
}
- @Override
public void remove() {
checkState(lastReturned != null);
LocalCache.this.remove(lastReturned.getKey());
@@ -4421,7 +4385,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
}
- final class KeyIterator extends HashIterator<K> {
+ final class KeyIterator extends HashIterator implements Iterator<K> {
@Override
public K next() {
@@ -4429,7 +4393,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
}
- final class ValueIterator extends HashIterator<V> {
+ final class ValueIterator extends HashIterator implements Iterator<V> {
@Override
public V next() {
@@ -4489,7 +4453,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
}
- final class EntryIterator extends HashIterator<Entry<K, V>> {
+ final class EntryIterator extends HashIterator implements Iterator<Entry<K, V>> {
@Override
public Entry<K, V> next() {
@@ -4497,73 +4461,68 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
}
- abstract class AbstractCacheSet<T> extends AbstractSet<T> {
- final ConcurrentMap<?, ?> map;
+ final class KeySet extends AbstractSet<K> {
- AbstractCacheSet(ConcurrentMap<?, ?> map) {
- this.map = map;
+ @Override
+ public Iterator<K> iterator() {
+ return new KeyIterator();
}
@Override
public int size() {
- return map.size();
+ return LocalCache.this.size();
}
@Override
public boolean isEmpty() {
- return map.isEmpty();
+ return LocalCache.this.isEmpty();
}
@Override
- public void clear() {
- map.clear();
+ public boolean contains(Object o) {
+ return LocalCache.this.containsKey(o);
}
- }
- final class KeySet extends AbstractCacheSet<K> {
-
- KeySet(ConcurrentMap<?, ?> map) {
- super(map);
+ @Override
+ public boolean remove(Object o) {
+ return LocalCache.this.remove(o) != null;
}
@Override
- public Iterator<K> iterator() {
- return new KeyIterator();
+ public void clear() {
+ LocalCache.this.clear();
}
+ }
+
+ final class Values extends AbstractCollection<V> {
@Override
- public boolean contains(Object o) {
- return map.containsKey(o);
+ public Iterator<V> iterator() {
+ return new ValueIterator();
}
@Override
- public boolean remove(Object o) {
- return map.remove(o) != null;
+ public int size() {
+ return LocalCache.this.size();
}
- }
-
- final class Values extends AbstractCacheSet<V> {
- Values(ConcurrentMap<?, ?> map) {
- super(map);
+ @Override
+ public boolean isEmpty() {
+ return LocalCache.this.isEmpty();
}
@Override
- public Iterator<V> iterator() {
- return new ValueIterator();
+ public boolean contains(Object o) {
+ return LocalCache.this.containsValue(o);
}
@Override
- public boolean contains(Object o) {
- return map.containsValue(o);
+ public void clear() {
+ LocalCache.this.clear();
}
}
- final class EntrySet extends AbstractCacheSet<Entry<K, V>> {
-
- EntrySet(ConcurrentMap<?, ?> map) {
- super(map);
- }
+ final class EntrySet extends AbstractSet<Entry<K, V>> {
@Override
public Iterator<Entry<K, V>> iterator() {
@@ -4594,6 +4553,21 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
Object key = e.getKey();
return key != null && LocalCache.this.remove(key, e.getValue());
}
+
+ @Override
+ public int size() {
+ return LocalCache.this.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return LocalCache.this.isEmpty();
+ }
+
+ @Override
+ public void clear() {
+ LocalCache.this.clear();
+ }
}
// Serialization Support
@@ -4663,15 +4637,15 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
this.loader = loader;
}
- CacheBuilder<K, V> recreateCacheBuilder() {
- CacheBuilder<K, V> builder = CacheBuilder.newBuilder()
+ CacheBuilder<Object, Object> recreateCacheBuilder() {
+ CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder()
.setKeyStrength(keyStrength)
.setValueStrength(valueStrength)
.keyEquivalence(keyEquivalence)
.valueEquivalence(valueEquivalence)
- .concurrencyLevel(concurrencyLevel)
- .removalListener(removalListener);
+ .concurrencyLevel(concurrencyLevel);
builder.strictParsing = false;
+ builder.removalListener(removalListener);
if (expireAfterWriteNanos > 0) {
builder.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS);
}
@@ -4696,7 +4670,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
- CacheBuilder<K, V> builder = recreateCacheBuilder();
+ CacheBuilder<Object, Object> builder = recreateCacheBuilder();
this.delegate = builder.build();
}
@@ -4730,7 +4704,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
- CacheBuilder<K, V> builder = recreateCacheBuilder();
+ CacheBuilder<Object, Object> builder = recreateCacheBuilder();
this.autoDelegate = builder.build(loader);
}
@@ -4768,18 +4742,19 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
final LocalCache<K, V> localCache;
LocalManualCache(CacheBuilder<? super K, ? super V> builder) {
- this(new LocalCache<K, V>(builder, null));
+ this(builder, null);
}
- private LocalManualCache(LocalCache<K, V> localCache) {
- this.localCache = localCache;
+ protected LocalManualCache(CacheBuilder<? super K, ? super V> builder,
+ CacheLoader<? super K, V> loader) {
+ this.localCache = new LocalCache<K, V>(builder, loader);
}
// Cache methods
@Override
@Nullable
- public V getIfPresent(Object key) {
+ public V getIfPresent(K key) {
return localCache.getIfPresent(key);
}
@@ -4795,7 +4770,7 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
@Override
- public ImmutableMap<K, V> getAllPresent(Iterable<?> keys) {
+ public ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys) {
return localCache.getAllPresent(keys);
}
@@ -4805,11 +4780,6 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
}
@Override
- public void putAll(Map<? extends K, ? extends V> m) {
- localCache.putAll(m);
- }
-
- @Override
public void invalidate(Object key) {
checkNotNull(key);
localCache.remove(key);
@@ -4850,6 +4820,27 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
localCache.cleanUp();
}
+ /*
+ * These methods have been moved to LoadingCache, but they temporarily
+ * remain in Cache in Guava.
+ */
+
+ public V get(K key) throws ExecutionException {
+ return localCache.getOrLoad(key);
+ }
+
+ public V getUnchecked(K key) {
+ try {
+ return get(key);
+ } catch (ExecutionException e) {
+ throw new UncheckedExecutionException(e.getCause());
+ }
+ }
+
+ public final V apply(K key) {
+ return getUnchecked(key);
+ }
+
// Serialization Support
private static final long serialVersionUID = 1;
@@ -4864,24 +4855,10 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
LocalLoadingCache(CacheBuilder<? super K, ? super V> builder,
CacheLoader<? super K, V> loader) {
- super(new LocalCache<K, V>(builder, checkNotNull(loader)));
+ super(builder, checkNotNull(loader));
}
- // LoadingCache methods
-
- @Override
- public V get(K key) throws ExecutionException {
- return localCache.getOrLoad(key);
- }
-
- @Override
- public V getUnchecked(K key) {
- try {
- return get(key);
- } catch (ExecutionException e) {
- throw new UncheckedExecutionException(e.getCause());
- }
- }
+ // Cache methods
@Override
public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
@@ -4893,16 +4870,10 @@ class LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
localCache.refresh(key);
}
- @Override
- public final V apply(K key) {
- return getUnchecked(key);
- }
-
// Serialization Support
private static final long serialVersionUID = 1;
- @Override
Object writeReplace() {
return new LoadingSerializationProxy<K, V>(localCache);
}
diff --git a/guava/src/com/google/common/cache/LongAddable.java b/guava/src/com/google/common/cache/LongAddable.java
deleted file mode 100644
index 48ddbfc..0000000
--- a/guava/src/com/google/common/cache/LongAddable.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2012 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;
-
-/**
- * Abstract interface for objects that can concurrently add longs.
- *
- * @author Louis Wasserman
- */
-@GwtCompatible
-interface LongAddable {
- void increment();
-
- void add(long x);
-
- long sum();
-}
diff --git a/guava/src/com/google/common/cache/LongAddables.java b/guava/src/com/google/common/cache/LongAddables.java
deleted file mode 100644
index a110c6c..0000000
--- a/guava/src/com/google/common/cache/LongAddables.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 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.base.Supplier;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- * Source of {@link LongAddable} objects that deals with GWT, Unsafe, and all
- * that.
- *
- * @author Louis Wasserman
- */
-@GwtCompatible(emulated = true)
-final class LongAddables {
- private static final Supplier<LongAddable> SUPPLIER;
-
- static {
- Supplier<LongAddable> supplier;
- try {
- new LongAdder();
- supplier = new Supplier<LongAddable>() {
- @Override
- public LongAddable get() {
- return new LongAdder();
- }
- };
- } catch (Throwable t) { // we really want to catch *everything*
- supplier = new Supplier<LongAddable>() {
- @Override
- public LongAddable get() {
- return new PureJavaLongAddable();
- }
- };
- }
- SUPPLIER = supplier;
- }
-
- public static LongAddable create() {
- return SUPPLIER.get();
- }
-
- private static final class PureJavaLongAddable extends AtomicLong implements LongAddable {
- @Override
- public void increment() {
- getAndIncrement();
- }
-
- @Override
- public void add(long x) {
- getAndAdd(x);
- }
-
- @Override
- public long sum() {
- return get();
- }
- }
-}
diff --git a/guava/src/com/google/common/cache/LongAdder.java b/guava/src/com/google/common/cache/LongAdder.java
deleted file mode 100644
index 5af81e1..0000000
--- a/guava/src/com/google/common/cache/LongAdder.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-/*
- * Source:
- * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.8
- */
-
-package com.google.common.cache;
-
-import com.google.common.annotations.GwtCompatible;
-
-import java.util.concurrent.atomic.AtomicLong;
-import java.io.IOException;
-import java.io.Serializable;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-/**
- * One or more variables that together maintain an initially zero
- * {@code long} sum. When updates (method {@link #add}) are contended
- * across threads, the set of variables may grow dynamically to reduce
- * contention. Method {@link #sum} (or, equivalently, {@link
- * #longValue}) returns the current total combined across the
- * variables maintaining the sum.
- *
- * <p> This class is usually preferable to {@link AtomicLong} when
- * multiple threads update a common sum that is used for purposes such
- * as collecting statistics, not for fine-grained synchronization
- * control. Under low update contention, the two classes have similar
- * characteristics. But under high contention, expected throughput of
- * this class is significantly higher, at the expense of higher space
- * consumption.
- *
- * <p>This class extends {@link Number}, but does <em>not</em> define
- * methods such as {@code hashCode} and {@code compareTo} because
- * instances are expected to be mutated, and so are not useful as
- * collection keys.
- *
- * <p><em>jsr166e note: This class is targeted to be placed in
- * java.util.concurrent.atomic<em>
- *
- * @since 1.8
- * @author Doug Lea
- */
-@GwtCompatible(emulated = true)
-final class LongAdder extends Striped64 implements Serializable, LongAddable {
- private static final long serialVersionUID = 7249069246863182397L;
-
- /**
- * Version of plus for use in retryUpdate
- */
- final long fn(long v, long x) { return v + x; }
-
- /**
- * Creates a new adder with initial sum of zero.
- */
- public LongAdder() {
- }
-
- /**
- * Adds the given value.
- *
- * @param x the value to add
- */
- public void add(long x) {
- Cell[] as; long b, v; HashCode hc; Cell a; int n;
- if ((as = cells) != null || !casBase(b = base, b + x)) {
- boolean uncontended = true;
- int h = (hc = threadHashCode.get()).code;
- if (as == null || (n = as.length) < 1 ||
- (a = as[(n - 1) & h]) == null ||
- !(uncontended = a.cas(v = a.value, v + x)))
- retryUpdate(x, hc, uncontended);
- }
- }
-
- /**
- * Equivalent to {@code add(1)}.
- */
- public void increment() {
- add(1L);
- }
-
- /**
- * Equivalent to {@code add(-1)}.
- */
- public void decrement() {
- add(-1L);
- }
-
- /**
- * Returns the current sum. The returned value is <em>NOT</em> an
- * atomic snapshot: Invocation in the absence of concurrent
- * updates returns an accurate result, but concurrent updates that
- * occur while the sum is being calculated might not be
- * incorporated.
- *
- * @return the sum
- */
- public long sum() {
- long sum = base;
- Cell[] as = cells;
- if (as != null) {
- int n = as.length;
- for (int i = 0; i < n; ++i) {
- Cell a = as[i];
- if (a != null)
- sum += a.value;
- }
- }
- return sum;
- }
-
- /**
- * Resets variables maintaining the sum to zero. This method may
- * be a useful alternative to creating a new adder, but is only
- * effective if there are no concurrent updates. Because this
- * method is intrinsically racy, it should only be used when it is
- * known that no threads are concurrently updating.
- */
- public void reset() {
- internalReset(0L);
- }
-
- /**
- * Equivalent in effect to {@link #sum} followed by {@link
- * #reset}. This method may apply for example during quiescent
- * points between multithreaded computations. If there are
- * updates concurrent with this method, the returned value is
- * <em>not</em> guaranteed to be the final value occurring before
- * the reset.
- *
- * @return the sum
- */
- public long sumThenReset() {
- long sum = base;
- Cell[] as = cells;
- base = 0L;
- if (as != null) {
- int n = as.length;
- for (int i = 0; i < n; ++i) {
- Cell a = as[i];
- if (a != null) {
- sum += a.value;
- a.value = 0L;
- }
- }
- }
- return sum;
- }
-
- /**
- * Returns the String representation of the {@link #sum}.
- * @return the String representation of the {@link #sum}
- */
- public String toString() {
- return Long.toString(sum());
- }
-
- /**
- * Equivalent to {@link #sum}.
- *
- * @return the sum
- */
- public long longValue() {
- return sum();
- }
-
- /**
- * Returns the {@link #sum} as an {@code int} after a narrowing
- * primitive conversion.
- */
- public int intValue() {
- return (int)sum();
- }
-
- /**
- * Returns the {@link #sum} as a {@code float}
- * after a widening primitive conversion.
- */
- public float floatValue() {
- return (float)sum();
- }
-
- /**
- * Returns the {@link #sum} as a {@code double} after a widening
- * primitive conversion.
- */
- public double doubleValue() {
- return (double)sum();
- }
-
- private void writeObject(ObjectOutputStream s)
- throws java.io.IOException {
- s.defaultWriteObject();
- s.writeLong(sum());
- }
-
- private void readObject(ObjectInputStream s)
- throws IOException, ClassNotFoundException {
- s.defaultReadObject();
- busy = 0;
- cells = null;
- base = s.readLong();
- }
-
-}
diff --git a/guava/src/com/google/common/cache/RemovalCause.java b/guava/src/com/google/common/cache/RemovalCause.java
index 0be9b5b..6574b0e 100644
--- a/guava/src/com/google/common/cache/RemovalCause.java
+++ b/guava/src/com/google/common/cache/RemovalCause.java
@@ -17,7 +17,6 @@
package com.google.common.cache;
import com.google.common.annotations.Beta;
-import com.google.common.annotations.GwtCompatible;
import java.util.Iterator;
import java.util.Map;
@@ -30,7 +29,6 @@ import java.util.concurrent.ConcurrentMap;
* @since 10.0
*/
@Beta
-@GwtCompatible
public enum RemovalCause {
/**
* The entry was manually removed by the user. This can result from the user invoking
diff --git a/guava/src/com/google/common/cache/RemovalListener.java b/guava/src/com/google/common/cache/RemovalListener.java
index 270a7c4..e9b6c2c 100644
--- a/guava/src/com/google/common/cache/RemovalListener.java
+++ b/guava/src/com/google/common/cache/RemovalListener.java
@@ -17,7 +17,6 @@
package com.google.common.cache;
import com.google.common.annotations.Beta;
-import com.google.common.annotations.GwtCompatible;
/**
* An object that can receive a notification when an entry is removed from a cache. The removal
@@ -37,7 +36,6 @@ import com.google.common.annotations.GwtCompatible;
* @since 10.0
*/
@Beta
-@GwtCompatible
public interface RemovalListener<K, V> {
/**
* Notifies the listener that a removal occurred at some point in the past.
diff --git a/guava/src/com/google/common/cache/RemovalListeners.java b/guava/src/com/google/common/cache/RemovalListeners.java
index dbb9efc..18292fd 100644
--- a/guava/src/com/google/common/cache/RemovalListeners.java
+++ b/guava/src/com/google/common/cache/RemovalListeners.java
@@ -16,8 +16,6 @@
package com.google.common.cache;
-import static com.google.common.base.Preconditions.checkNotNull;
-
import com.google.common.annotations.Beta;
import java.util.concurrent.Executor;
@@ -43,8 +41,6 @@ public final class RemovalListeners {
*/
public static <K, V> RemovalListener<K, V> asynchronous(
final RemovalListener<K, V> listener, final Executor executor) {
- checkNotNull(listener);
- checkNotNull(executor);
return new RemovalListener<K, V>() {
@Override
public void onRemoval(final RemovalNotification<K, V> notification) {
diff --git a/guava/src/com/google/common/cache/RemovalNotification.java b/guava/src/com/google/common/cache/RemovalNotification.java
index 2565dba..8e0066e 100644
--- a/guava/src/com/google/common/cache/RemovalNotification.java
+++ b/guava/src/com/google/common/cache/RemovalNotification.java
@@ -19,7 +19,6 @@ package com.google.common.cache;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.Beta;
-import com.google.common.annotations.GwtCompatible;
import com.google.common.base.Objects;
import java.util.Map.Entry;
@@ -38,7 +37,6 @@ import javax.annotation.Nullable;
* @since 10.0
*/
@Beta
-@GwtCompatible
public final class RemovalNotification<K, V> implements Entry<K, V> {
@Nullable private final K key;
@Nullable private final V value;
diff --git a/guava/src/com/google/common/cache/Striped64.java b/guava/src/com/google/common/cache/Striped64.java
deleted file mode 100644
index e045453..0000000
--- a/guava/src/com/google/common/cache/Striped64.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-/*
- * Source:
- * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.7
- */
-
-package com.google.common.cache;
-
-import java.util.Random;
-
-/**
- * A package-local class holding common representation and mechanics
- * for classes supporting dynamic striping on 64bit values. The class
- * extends Number so that concrete subclasses must publicly do so.
- */
-abstract class Striped64 extends Number {
- /*
- * This class maintains a lazily-initialized table of atomically
- * updated variables, plus an extra "base" field. The table size
- * is a power of two. Indexing uses masked per-thread hash codes.
- * Nearly all declarations in this class are package-private,
- * accessed directly by subclasses.
- *
- * Table entries are of class Cell; a variant of AtomicLong padded
- * to reduce cache contention on most processors. Padding is
- * overkill for most Atomics because they are usually irregularly
- * scattered in memory and thus don't interfere much with each
- * other. But Atomic objects residing in arrays will tend to be
- * placed adjacent to each other, and so will most often share
- * cache lines (with a huge negative performance impact) without
- * this precaution.
- *
- * In part because Cells are relatively large, we avoid creating
- * them until they are needed. When there is no contention, all
- * updates are made to the base field. Upon first contention (a
- * failed CAS on base update), the table is initialized to size 2.
- * The table size is doubled upon further contention until
- * reaching the nearest power of two greater than or equal to the
- * number of CPUS. Table slots remain empty (null) until they are
- * needed.
- *
- * A single spinlock ("busy") is used for initializing and
- * resizing the table, as well as populating slots with new Cells.
- * There is no need for a blocking lock: When the lock is not
- * available, threads try other slots (or the base). During these
- * retries, there is increased contention and reduced locality,
- * which is still better than alternatives.
- *
- * Per-thread hash codes are initialized to random values.
- * Contention and/or table collisions are indicated by failed
- * CASes when performing an update operation (see method
- * retryUpdate). Upon a collision, if the table size is less than
- * the capacity, it is doubled in size unless some other thread
- * holds the lock. If a hashed slot is empty, and lock is
- * available, a new Cell is created. Otherwise, if the slot
- * exists, a CAS is tried. Retries proceed by "double hashing",
- * using a secondary hash (Marsaglia XorShift) to try to find a
- * free slot.
- *
- * The table size is capped because, when there are more threads
- * than CPUs, supposing that each thread were bound to a CPU,
- * there would exist a perfect hash function mapping threads to
- * slots that eliminates collisions. When we reach capacity, we
- * search for this mapping by randomly varying the hash codes of
- * colliding threads. Because search is random, and collisions
- * only become known via CAS failures, convergence can be slow,
- * and because threads are typically not bound to CPUS forever,
- * may not occur at all. However, despite these limitations,
- * observed contention rates are typically low in these cases.
- *
- * It is possible for a Cell to become unused when threads that
- * once hashed to it terminate, as well as in the case where
- * doubling the table causes no thread to hash to it under
- * expanded mask. We do not try to detect or remove such cells,
- * under the assumption that for long-running instances, observed
- * contention levels will recur, so the cells will eventually be
- * needed again; and for short-lived ones, it does not matter.
- */
-
- /**
- * Padded variant of AtomicLong supporting only raw accesses plus CAS.
- * The value field is placed between pads, hoping that the JVM doesn't
- * reorder them.
- *
- * JVM intrinsics note: It would be possible to use a release-only
- * form of CAS here, if it were provided.
- */
- static final class Cell {
- volatile long p0, p1, p2, p3, p4, p5, p6;
- volatile long value;
- volatile long q0, q1, q2, q3, q4, q5, q6;
- Cell(long x) { value = x; }
-
- final boolean cas(long cmp, long val) {
- return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
- }
-
- // Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long valueOffset;
- static {
- try {
- UNSAFE = getUnsafe();
- Class<?> ak = Cell.class;
- valueOffset = UNSAFE.objectFieldOffset
- (ak.getDeclaredField("value"));
- } catch (Exception e) {
- throw new Error(e);
- }
- }
-
- }
-
- /**
- * Holder for the thread-local hash code. The code is initially
- * random, but may be set to a different value upon collisions.
- */
- static final class HashCode {
- static final Random rng = new Random();
- int code;
- HashCode() {
- int h = rng.nextInt(); // Avoid zero to allow xorShift rehash
- code = (h == 0) ? 1 : h;
- }
- }
-
- /**
- * The corresponding ThreadLocal class
- */
- static final class ThreadHashCode extends ThreadLocal<HashCode> {
- public HashCode initialValue() { return new HashCode(); }
- }
-
- /**
- * Static per-thread hash codes. Shared across all instances to
- * reduce ThreadLocal pollution and because adjustments due to
- * collisions in one table are likely to be appropriate for
- * others.
- */
- static final ThreadHashCode threadHashCode = new ThreadHashCode();
-
- /** Number of CPUS, to place bound on table size */
- static final int NCPU = Runtime.getRuntime().availableProcessors();
-
- /**
- * Table of cells. When non-null, size is a power of 2.
- */
- transient volatile Cell[] cells;
-
- /**
- * Base value, used mainly when there is no contention, but also as
- * a fallback during table initialization races. Updated via CAS.
- */
- transient volatile long base;
-
- /**
- * Spinlock (locked via CAS) used when resizing and/or creating Cells.
- */
- transient volatile int busy;
-
- /**
- * Package-private default constructor
- */
- Striped64() {
- }
-
- /**
- * CASes the base field.
- */
- final boolean casBase(long cmp, long val) {
- return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
- }
-
- /**
- * CASes the busy field from 0 to 1 to acquire lock.
- */
- final boolean casBusy() {
- return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
- }
-
- /**
- * Computes the function of current and new value. Subclasses
- * should open-code this update function for most uses, but the
- * virtualized form is needed within retryUpdate.
- *
- * @param currentValue the current value (of either base or a cell)
- * @param newValue the argument from a user update call
- * @return result of the update function
- */
- abstract long fn(long currentValue, long newValue);
-
- /**
- * Handles cases of updates involving initialization, resizing,
- * creating new Cells, and/or contention. See above for
- * explanation. This method suffers the usual non-modularity
- * problems of optimistic retry code, relying on rechecked sets of
- * reads.
- *
- * @param x the value
- * @param hc the hash code holder
- * @param wasUncontended false if CAS failed before call
- */
- final void retryUpdate(long x, HashCode hc, boolean wasUncontended) {
- int h = hc.code;
- boolean collide = false; // True if last slot nonempty
- for (;;) {
- Cell[] as; Cell a; int n; long v;
- if ((as = cells) != null && (n = as.length) > 0) {
- if ((a = as[(n - 1) & h]) == null) {
- if (busy == 0) { // Try to attach new Cell
- Cell r = new Cell(x); // Optimistically create
- if (busy == 0 && casBusy()) {
- boolean created = false;
- try { // Recheck under lock
- Cell[] rs; int m, j;
- if ((rs = cells) != null &&
- (m = rs.length) > 0 &&
- rs[j = (m - 1) & h] == null) {
- rs[j] = r;
- created = true;
- }
- } finally {
- busy = 0;
- }
- if (created)
- break;
- continue; // Slot is now non-empty
- }
- }
- collide = false;
- }
- else if (!wasUncontended) // CAS already known to fail
- wasUncontended = true; // Continue after rehash
- else if (a.cas(v = a.value, fn(v, x)))
- break;
- else if (n >= NCPU || cells != as)
- collide = false; // At max size or stale
- else if (!collide)
- collide = true;
- else if (busy == 0 && casBusy()) {
- try {
- if (cells == as) { // Expand table unless stale
- Cell[] rs = new Cell[n << 1];
- for (int i = 0; i < n; ++i)
- rs[i] = as[i];
- cells = rs;
- }
- } finally {
- busy = 0;
- }
- collide = false;
- continue; // Retry with expanded table
- }
- h ^= h << 13; // Rehash
- h ^= h >>> 17;
- h ^= h << 5;
- }
- else if (busy == 0 && cells == as && casBusy()) {
- boolean init = false;
- try { // Initialize table
- if (cells == as) {
- Cell[] rs = new Cell[2];
- rs[h & 1] = new Cell(x);
- cells = rs;
- init = true;
- }
- } finally {
- busy = 0;
- }
- if (init)
- break;
- }
- else if (casBase(v = base, fn(v, x)))
- break; // Fall back on using base
- }
- hc.code = h; // Record index for next time
- }
-
- /**
- * Sets base and all cells to the given value.
- */
- final void internalReset(long initialValue) {
- Cell[] as = cells;
- base = initialValue;
- if (as != null) {
- int n = as.length;
- for (int i = 0; i < n; ++i) {
- Cell a = as[i];
- if (a != null)
- a.value = initialValue;
- }
- }
- }
-
- // Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long baseOffset;
- private static final long busyOffset;
- static {
- try {
- UNSAFE = getUnsafe();
- Class<?> sk = Striped64.class;
- baseOffset = UNSAFE.objectFieldOffset
- (sk.getDeclaredField("base"));
- busyOffset = UNSAFE.objectFieldOffset
- (sk.getDeclaredField("busy"));
- } catch (Exception e) {
- throw new Error(e);
- }
- }
-
- /**
- * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
- * Replace with a simple call to Unsafe.getUnsafe when integrating
- * into a jdk.
- *
- * @return a sun.misc.Unsafe
- */
- private static sun.misc.Unsafe getUnsafe() {
- try {
- return sun.misc.Unsafe.getUnsafe();
- } catch (SecurityException tryReflectionInstead) {}
- try {
- return java.security.AccessController.doPrivileged
- (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
- public sun.misc.Unsafe run() throws Exception {
- Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
- for (java.lang.reflect.Field f : k.getDeclaredFields()) {
- f.setAccessible(true);
- Object x = f.get(null);
- if (k.isInstance(x))
- return k.cast(x);
- }
- throw new NoSuchFieldError("the Unsafe");
- }});
- } catch (java.security.PrivilegedActionException e) {
- throw new RuntimeException("Could not initialize intrinsics",
- e.getCause());
- }
- }
-
-}
diff --git a/guava/src/com/google/common/cache/Weigher.java b/guava/src/com/google/common/cache/Weigher.java
index 5720cb8..bbb0a33 100644
--- a/guava/src/com/google/common/cache/Weigher.java
+++ b/guava/src/com/google/common/cache/Weigher.java
@@ -1,30 +1,30 @@
/*
* 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
+ * 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.
+ * 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.Beta;
-import com.google.common.annotations.GwtCompatible;
/**
* Calculates the weights of cache entries.
*
- * @author Charles Fry
+ * @author fry@google.com (Charles Fry)
* @since 11.0
*/
@Beta
-@GwtCompatible
public interface Weigher<K, V> {
/**
@@ -34,4 +34,5 @@ public interface Weigher<K, V> {
* @return the weight of the entry; must be non-negative
*/
int weigh(K key, V value);
+
}
diff --git a/guava/src/com/google/common/cache/package-info.java b/guava/src/com/google/common/cache/package-info.java
index ea0297b..1c5391c 100644
--- a/guava/src/com/google/common/cache/package-info.java
+++ b/guava/src/com/google/common/cache/package-info.java
@@ -22,9 +22,6 @@
* {@link com.google.common.cache.CacheBuilder}, with cache entries being loaded by
* {@link com.google.common.cache.CacheLoader}. Statistics about cache performance are exposed using
* {@link com.google.common.cache.CacheStats}.
- *
- * <p>See the Guava User Guide article on <a href=
- * "http://code.google.com/p/guava-libraries/wiki/CachesExplained">caches</a>.
*
* <p>This package is a part of the open-source
* <a href="http://guava-libraries.googlecode.com">Guava libraries</a>.
@@ -35,4 +32,3 @@
package com.google.common.cache;
import javax.annotation.ParametersAreNonnullByDefault;
-