11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.cache;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkState;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.CacheBuilder.NULL_TICKER;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.cache.CacheBuilder.UNSET_INT;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.util.concurrent.Uninterruptibles.getUninterruptibly;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.concurrent.TimeUnit.NANOSECONDS;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.VisibleForTesting;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Equivalence;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Equivalences;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Stopwatch;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Ticker;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.AbstractCache.SimpleStatsCounter;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.AbstractCache.StatsCounter;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.CacheBuilder.NullListener;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.CacheBuilder.OneWeigher;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.CacheLoader.InvalidCacheLoadException;
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.CacheLoader.UnsupportedLoadingOperationException;
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.AbstractLinkedIterator;
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.ImmutableMap;
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Iterators;
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Maps;
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Sets;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.primitives.Ints;
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.ExecutionError;
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.Futures;
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.ListenableFuture;
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.ListeningExecutorService;
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.MoreExecutors;
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.SettableFuture;
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.util.concurrent.UncheckedExecutionException;
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.IOException;
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.ObjectInputStream;
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.Serializable;
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.Reference;
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.ReferenceQueue;
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.SoftReference;
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.ref.WeakReference;
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractCollection;
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractMap;
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractQueue;
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractSet;
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator;
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map;
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.NoSuchElementException;
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Queue;
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set;
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.Callable;
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentLinkedQueue;
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentMap;
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException;
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.TimeUnit;
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicInteger;
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.atomic.AtomicReferenceArray;
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.locks.ReentrantLock;
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Level;
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Logger;
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.concurrent.GuardedBy;
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The concurrent hash map implementation built by {@link CacheBuilder}.
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This implementation is heavily derived from revision 1.96 of <a
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * href="http://tinyurl.com/ConcurrentHashMap">ConcurrentHashMap.java</a>.
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Charles Fry
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Bob Lee ({@code com.google.common.collect.MapMaker})
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Doug Lea ({@code ConcurrentHashMap})
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertclass LocalCache<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> {
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The basic strategy is to subdivide the table among Segments, each of which itself is a
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * concurrently readable hash table. The map supports non-blocking reads and concurrent writes
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * across different segments.
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * If a maximum size is specified, a best-effort bounding is performed per segment, using a
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * page-replacement algorithm to determine which entries to evict when the capacity has been
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * exceeded.
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The page replacement algorithm's data structures are kept casually consistent with the map. The
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ordering of writes to a segment is sequentially consistent. An update to the map and recording
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of reads may not be immediately reflected on the algorithm's data structures. These structures
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * are guarded by a lock and operations are applied in batches to avoid lock contention. The
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * penalty of applying the batches is spread across threads so that the amortized cost is slightly
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * higher than performing just the operation without enforcing the capacity constraint.
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This implementation uses a per-segment queue to record a memento of the additions, removals,
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * and accesses that were performed on the map. The queue is drained on writes and when it exceeds
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * its capacity threshold.
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The Least Recently Used page replacement algorithm was chosen due to its simplicity, high hit
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * rate, and ability to be implemented with O(1) time complexity. The initial LRU implementation
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * operates per-segment rather than globally for increased implementation simplicity. We expect
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the cache hit rate to be similar to that of a global LRU algorithm.
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Constants
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The maximum capacity, used if a higher value is implicitly specified by either of the
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * constructors with arguments. MUST be a power of two <= 1<<30 to ensure that entries are
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * indexable using ints.
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final int MAXIMUM_CAPACITY = 1 << 30;
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** The maximum number of segments to allow; used to bound constructor arguments. */
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Number of (unsynchronized) retries in the containsValue method. */
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final int CONTAINS_VALUE_RETRIES = 3;
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Number of cache access operations that can be buffered per segment before the cache's recency
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ordering information is updated. This is used to avoid lock contention by recording a memento
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of reads and delaying a lock acquisition until the threshold is crossed or a mutation occurs.
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>This must be a (2^n)-1 as it is used as a mask.
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final int DRAIN_THRESHOLD = 0x3F;
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Maximum number of entries to be drained in a single cleanup run. This applies independently to
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the cleanup queue and both reference queues.
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // TODO(fry): empirically optimize this
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final int DRAIN_MAX = 16;
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Fields
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final Logger logger = Logger.getLogger(LocalCache.class.getName());
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final ListeningExecutorService sameThreadExecutor = MoreExecutors.sameThreadExecutor();
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Mask value for indexing into segments. The upper bits of a key's hash code are used to choose
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the segment.
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final int segmentMask;
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Shift value for indexing within segments. Helps prevent entries that end up in the same segment
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * from also ending up in the same bucket.
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final int segmentShift;
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** The segments, each of which is a specialized hash table. */
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Segment<K, V>[] segments;
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** The concurrency level. */
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final int concurrencyLevel;
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Strategy for comparing keys. */
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Equivalence<Object> keyEquivalence;
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Strategy for comparing values. */
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Equivalence<Object> valueEquivalence;
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Strategy for referencing keys. */
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Strength keyStrength;
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Strategy for referencing values. */
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Strength valueStrength;
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** The maximum weight of this map. UNSET_INT if there is no maximum. */
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final long maxWeight;
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Weigher to weigh cache entries. */
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Weigher<K, V> weigher;
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** How long after the last access to an entry the map will retain that entry. */
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final long expireAfterAccessNanos;
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** How long after the last write to an entry the map will retain that entry. */
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final long expireAfterWriteNanos;
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** How long after the last write an entry becomes a candidate for refresh. */
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final long refreshNanos;
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Entries waiting to be consumed by the removal listener. */
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // TODO(fry): define a new type which creates event objects and automates the clear logic
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Queue<RemovalNotification<K, V>> removalNotificationQueue;
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A listener that is invoked when an entry is removed due to expiration or garbage collection of
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * soft/weak entries.
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final RemovalListener<K, V> removalListener;
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Measures time in a testable way. */
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Ticker ticker;
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** Factory used to create new entries. */
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final EntryFactory entryFactory;
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Accumulates global cache statistics. Note that there are also per-segments stats counters
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * which must be aggregated to obtain a global stats view.
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final StatsCounter globalStatsCounter;
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The default cache loader to use on loading operations.
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final CacheLoader<? super K, V> defaultLoader;
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a new, empty map with the specified strategy, initial capacity and concurrency level.
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  LocalCache(CacheBuilder<? super K, ? super V> builder, CacheLoader<? super K, V> loader) {
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    concurrencyLevel = Math.min(builder.getConcurrencyLevel(), MAX_SEGMENTS);
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    keyStrength = builder.getKeyStrength();
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    valueStrength = builder.getValueStrength();
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    keyEquivalence = builder.getKeyEquivalence();
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    valueEquivalence = builder.getValueEquivalence();
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    maxWeight = builder.getMaximumWeight();
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    weigher = builder.getWeigher();
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    expireAfterAccessNanos = builder.getExpireAfterAccessNanos();
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    expireAfterWriteNanos = builder.getExpireAfterWriteNanos();
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    refreshNanos = builder.getRefreshNanos();
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    removalListener = builder.getRemovalListener();
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    removalNotificationQueue = (removalListener == NullListener.INSTANCE)
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ? LocalCache.<RemovalNotification<K, V>>discardingQueue()
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        : new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ticker = builder.getTicker(recordsTime());
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    entryFactory = EntryFactory.getFactory(keyStrength, usesAccessEntries(), usesWriteEntries());
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    globalStatsCounter = builder.getStatsCounterSupplier().get();
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    defaultLoader = loader;
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int initialCapacity = Math.min(builder.getInitialCapacity(), MAXIMUM_CAPACITY);
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (evictsBySize() && !customWeigher()) {
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      initialCapacity = Math.min(initialCapacity, (int) maxWeight);
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Find power-of-two sizes best matching arguments. Constraints:
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // (segmentCount <= maxWeight)
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // && (concurrencyLevel > maxWeight || segmentCount > concurrencyLevel)
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int segmentShift = 0;
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int segmentCount = 1;
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    while (segmentCount < concurrencyLevel
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        && (!evictsBySize() || customWeigher() || segmentCount * 2 <= maxWeight)) {
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ++segmentShift;
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      segmentCount <<= 1;
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.segmentShift = 32 - segmentShift;
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    segmentMask = segmentCount - 1;
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.segments = newSegmentArray(segmentCount);
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int segmentCapacity = initialCapacity / segmentCount;
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (segmentCapacity * segmentCount < initialCapacity) {
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ++segmentCapacity;
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int segmentSize = 1;
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    while (segmentSize < segmentCapacity) {
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      segmentSize <<= 1;
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (evictsBySize()) {
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Ensure sum of segment max weights = overall max weights
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long maxSegmentWeight = maxWeight / segmentCount + 1;
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long remainder = maxWeight % segmentCount;
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < this.segments.length; ++i) {
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (i == remainder) {
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          maxSegmentWeight--;
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.segments[i] =
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            createSegment(segmentSize, maxSegmentWeight, builder.getStatsCounterSupplier().get());
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < this.segments.length; ++i) {
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.segments[i] =
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            createSegment(segmentSize, UNSET_INT, builder.getStatsCounterSupplier().get());
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean evictsBySize() {
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return maxWeight >= 0;
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean customWeigher() {
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return weigher != OneWeigher.INSTANCE;
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean expires() {
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expiresAfterWrite() || expiresAfterAccess();
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean expiresAfterWrite() {
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expireAfterWriteNanos > 0;
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean expiresAfterAccess() {
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expireAfterAccessNanos > 0;
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean refreshes() {
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return refreshNanos > 0;
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean usesAccessQueue() {
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expiresAfterAccess() || evictsBySize();
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean usesWriteQueue() {
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expiresAfterWrite();
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean recordsWrite() {
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expiresAfterWrite() || refreshes();
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean recordsAccess() {
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return expiresAfterAccess();
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean recordsTime() {
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return recordsWrite() || recordsAccess();
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean usesWriteEntries() {
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return usesWriteQueue() || recordsWrite();
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean usesAccessEntries() {
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return usesAccessQueue() || recordsAccess();
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean usesKeyReferences() {
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return keyStrength != Strength.STRONG;
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean usesValueReferences() {
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return valueStrength != Strength.STRONG;
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  enum Strength {
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * TODO(kevinb): If we strongly reference the value and aren't loading, we needn't wrap the
3701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * value. This could save ~8 bytes per entry.
3711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
3721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    STRONG {
3741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
3751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ValueReference<K, V> referenceValue(
3761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> entry, V value, int weight) {
3771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return (weight == 1)
3781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ? new StrongValueReference<K, V>(value)
3791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            : new WeightedStrongValueReference<K, V>(value, weight);
3801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
3831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Equivalence<Object> defaultEquivalence() {
3841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Equivalences.equals();
3851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
3871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SOFT {
3891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
3901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ValueReference<K, V> referenceValue(
3911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> entry, V value, int weight) {
3921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return (weight == 1)
3931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ? new SoftValueReference<K, V>(segment.valueReferenceQueue, value, entry)
3941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            : new WeightedSoftValueReference<K, V>(
3951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                segment.valueReferenceQueue, value, entry, weight);
3961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
3991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Equivalence<Object> defaultEquivalence() {
4001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Equivalences.identity();
4011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
4031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WEAK {
4051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ValueReference<K, V> referenceValue(
4071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> entry, V value, int weight) {
4081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return (weight == 1)
4091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ? new WeakValueReference<K, V>(segment.valueReferenceQueue, value, entry)
4101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            : new WeightedWeakValueReference<K, V>(
4111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                segment.valueReferenceQueue, value, entry, weight);
4121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Equivalence<Object> defaultEquivalence() {
4161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Equivalences.identity();
4171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
4191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
4211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Creates a reference for the given value according to this value strength.
4221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
4231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    abstract <K, V> ValueReference<K, V> referenceValue(
4241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Segment<K, V> segment, ReferenceEntry<K, V> entry, V value, int weight);
4251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
4271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the default equivalence strategy used to compare and hash keys or values referenced
4281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * at this strength. This strategy will be used unless the user explicitly specifies an
4291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * alternate strategy.
4301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
4311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    abstract Equivalence<Object> defaultEquivalence();
4321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
4331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
4351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates new entries.
4361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
4371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  enum EntryFactory {
4381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    STRONG {
4391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
4411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
4421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new StrongEntry<K, V>(key, hash, next);
4431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
4451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    STRONG_ACCESS {
4461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
4481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
4491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new StrongAccessEntry<K, V>(key, hash, next);
4501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> copyEntry(
4541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
4551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
4561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyAccessEntry(original, newEntry);
4571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return newEntry;
4581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
4601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    STRONG_WRITE {
4611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
4631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
4641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new StrongWriteEntry<K, V>(key, hash, next);
4651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> copyEntry(
4691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
4701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
4711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyWriteEntry(original, newEntry);
4721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return newEntry;
4731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
4751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    STRONG_ACCESS_WRITE {
4761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
4781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
4791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new StrongAccessWriteEntry<K, V>(key, hash, next);
4801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> copyEntry(
4841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
4851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
4861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyAccessEntry(original, newEntry);
4871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyWriteEntry(original, newEntry);
4881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return newEntry;
4891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
4911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
4921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WEAK {
4931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
4941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
4951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
4961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new WeakEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
4971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
4981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
4991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WEAK_ACCESS {
5001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
5011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
5021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
5031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new WeakAccessEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
5041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
5071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> copyEntry(
5081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
5091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
5101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyAccessEntry(original, newEntry);
5111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return newEntry;
5121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
5141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WEAK_WRITE {
5151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
5161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
5171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
5181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new WeakWriteEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
5191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
5221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> copyEntry(
5231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
5241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
5251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyWriteEntry(original, newEntry);
5261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return newEntry;
5271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    },
5291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WEAK_ACCESS_WRITE {
5301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
5311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> newEntry(
5321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
5331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return new WeakAccessWriteEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
5341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
5371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      <K, V> ReferenceEntry<K, V> copyEntry(
5381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
5391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
5401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyAccessEntry(original, newEntry);
5411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        copyWriteEntry(original, newEntry);
5421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return newEntry;
5431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
5441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
5451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
5471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Masks used to compute indices in the following table.
5481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
5491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    static final int ACCESS_MASK = 1;
5501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    static final int WRITE_MASK = 2;
5511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    static final int WEAK_MASK = 4;
5521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
5541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Look-up table for factories.
5551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
5561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    static final EntryFactory[] factories = {
5571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      STRONG, STRONG_ACCESS, STRONG_WRITE, STRONG_ACCESS_WRITE,
5581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      WEAK, WEAK_ACCESS, WEAK_WRITE, WEAK_ACCESS_WRITE,
5591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
5601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    static EntryFactory getFactory(Strength keyStrength, boolean usesAccessQueue,
5621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        boolean usesWriteQueue) {
5631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int flags = ((keyStrength == Strength.WEAK) ? WEAK_MASK : 0)
5641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          | (usesAccessQueue ? ACCESS_MASK : 0)
5651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          | (usesWriteQueue ? WRITE_MASK : 0);
5661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return factories[flags];
5671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
5701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Creates a new entry.
5711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
5721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param segment to create the entry for
5731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param key of the entry
5741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param hash of the key
5751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param next entry in the same bucket
5761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
5771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    abstract <K, V> ReferenceEntry<K, V> newEntry(
5781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next);
5791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
5811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Copies an entry, assigning it a new {@code next} entry.
5821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
5831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param original the entry to copy
5841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @param newNext entry in the same bucket
5851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
5861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
5871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    <K, V> ReferenceEntry<K, V> copyEntry(
5881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
5891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return newEntry(segment, original.getKey(), original.getHash(), newNext);
5901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
5911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
5931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    <K, V> void copyAccessEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newEntry) {
5941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // TODO(fry): when we link values instead of entries this method can go
5951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // away, as can connectAccessOrder, nullifyAccessOrder.
5961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      newEntry.setAccessTime(original.getAccessTime());
5971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
5981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectAccessOrder(original.getPreviousInAccessQueue(), newEntry);
5991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectAccessOrder(newEntry, original.getNextInAccessQueue());
6001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nullifyAccessOrder(original);
6021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
6051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    <K, V> void copyWriteEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newEntry) {
6061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // TODO(fry): when we link values instead of entries this method can go
6071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // away, as can connectWriteOrder, nullifyWriteOrder.
6081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      newEntry.setWriteTime(original.getWriteTime());
6091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectWriteOrder(original.getPreviousInWriteQueue(), newEntry);
6111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectWriteOrder(newEntry, original.getNextInWriteQueue());
6121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nullifyWriteOrder(original);
6141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A reference to a value.
6191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  interface ValueReference<K, V> {
6211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the value. Does not block or throw exceptions.
6231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
6251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V get();
6261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Waits for a value that may still be loading. Unlike get(), this method can block (in the
6291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * case of FutureValueReference).
6301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
6311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @throws ExecutionException if the loading thread throws an exception
6321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * @throws ExecutionError if the loading thread throws an error
6331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V waitForValue() throws ExecutionException;
6351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the weight of this entry. This is assumed to be static between calls to setValue.
6381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int getWeight();
6401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the entry associated with this value reference, or {@code null} if this value
6431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * reference is independent of any entry.
6441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
6461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getEntry();
6471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Creates a copy of this reference for the given entry.
6501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry);
6521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Notifify pending loads that a new value was set. This is only relevant to loading
6551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * value references.
6561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void notifyNewValue(@Nullable V newValue);
6581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns true if a new value is currently loading, regardless of whether or not there is an
6611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * existing value. It is assumed that the return value of this method is constant for any given
6621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * ValueReference instance.
6631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean isLoading();
6651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
6671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns true if this reference contains an active value, meaning one that is still considered
6681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * present in the cache. Active values consist of live values, which are returned by cache
6691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * lookups, and dead values, which have been evicted but awaiting removal. Non-active values
6701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * consist strictly of loading values, though during refresh a value may be both active and
6711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * loading.
6721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
6731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean isActive();
6741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
6751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
6771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Placeholder. Indicates that the value hasn't been set yet.
6781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
6791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final ValueReference<Object, Object> UNSET = new ValueReference<Object, Object>() {
6801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
6811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Object get() {
6821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
6831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
6861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
6871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 0;
6881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
6911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<Object, Object> getEntry() {
6921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
6931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
6941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
6951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
6961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<Object, Object> copyFor(
6971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceQueue<Object> queue, ReferenceEntry<Object, Object> entry) {
6981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
6991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
7021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isLoading() {
7031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
7041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
7071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isActive() {
7081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
7091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
7121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Object waitForValue() {
7131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
7141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
7151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
7171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void notifyNewValue(Object newValue) {}
7181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  };
7191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Singleton placeholder that indicates a value is being loaded.
7221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value
7241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <K, V> ValueReference<K, V> unset() {
7251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (ValueReference<K, V>) UNSET;
7261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
7271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
7291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * An entry in a reference map.
7301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Entries in the map can be in the following states:
7321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Valid:
7341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Live: valid key/value are set
7351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Loading: loading is pending
7361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
7371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Invalid:
7381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Expired: time expired (key/value may still be set)
7391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Collected: key/value was partially collected, but not yet cleaned up
7401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * - Unset: marked as unset, awaiting cleanup or reuse
7411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
7421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  interface ReferenceEntry<K, V> {
7431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the value reference from this entry.
7451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ValueReference<K, V> getValueReference();
7471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the value reference for this entry.
7501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setValueReference(ValueReference<K, V> valueReference);
7521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the next entry in the chain.
7551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
7571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getNext();
7581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the entry's hash.
7611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int getHash();
7631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the key for this entry.
7661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
7681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    K getKey();
7691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
7711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Used by entries that use access order. Access entries are maintained in a doubly-linked list.
7721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * New entries are added at the tail of the list at write time; stale entries are expired from
7731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * the head of the list.
7741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the time that this entry was last accessed, in ns.
7781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long getAccessTime();
7801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the entry access time in ns.
7831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setAccessTime(long time);
7851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the next entry in the access queue.
7881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getNextInAccessQueue();
7901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the next entry in the access queue.
7931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setNextInAccessQueue(ReferenceEntry<K, V> next);
7951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
7961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
7971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the previous entry in the access queue.
7981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
7991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getPreviousInAccessQueue();
8001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the previous entry in the access queue.
8031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setPreviousInAccessQueue(ReferenceEntry<K, V> previous);
8051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
8071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Implemented by entries that use write order. Write entries are maintained in a
8081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * doubly-linked list. New entries are added at the tail of the list at write time and stale
8091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * entries are expired from the head of the list.
8101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the time that this entry was last written, in ns.
8141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long getWriteTime();
8161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the entry write time in ns.
8191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setWriteTime(long time);
8211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the next entry in the write queue.
8241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getNextInWriteQueue();
8261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the next entry in the write queue.
8291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setNextInWriteQueue(ReferenceEntry<K, V> next);
8311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the previous entry in the write queue.
8341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getPreviousInWriteQueue();
8361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
8381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets the previous entry in the write queue.
8391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
8401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setPreviousInWriteQueue(ReferenceEntry<K, V> previous);
8411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
8421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private enum NullEntry implements ReferenceEntry<Object, Object> {
8441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    INSTANCE;
8451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<Object, Object> getValueReference() {
8481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
8491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setValueReference(ValueReference<Object, Object> valueReference) {}
8531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<Object, Object> getNext() {
8561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
8571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getHash() {
8611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 0;
8621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Object getKey() {
8661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
8671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
8711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 0;
8721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {}
8761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<Object, Object> getNextInAccessQueue() {
8791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
8801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<Object, Object> next) {}
8841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<Object, Object> getPreviousInAccessQueue() {
8871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
8881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<Object, Object> previous) {}
8921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
8951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 0;
8961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
8971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
8981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
8991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {}
9001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<Object, Object> getNextInWriteQueue() {
9031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
9041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<Object, Object> next) {}
9081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<Object, Object> getPreviousInWriteQueue() {
9111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
9121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<Object, Object> previous) {}
9161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
9171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static abstract class AbstractReferenceEntry<K, V> implements ReferenceEntry<K, V> {
9191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> getValueReference() {
9211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setValueReference(ValueReference<K, V> valueReference) {
9261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNext() {
9311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getHash() {
9361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public K getKey() {
9411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
9461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
9511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
9561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
9611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
9661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
9711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
9761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
9811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
9861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
9911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
9951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
9961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
9971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
9981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
9991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
10011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
10021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value
10061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <K, V> ReferenceEntry<K, V> nullEntry() {
10071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (ReferenceEntry<K, V>) NullEntry.INSTANCE;
10081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final Queue<? extends Object> DISCARDING_QUEUE = new AbstractQueue<Object>() {
10111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean offer(Object o) {
10131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
10141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Object peek() {
10181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
10191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Object poll() {
10231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
10241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int size() {
10281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 0;
10291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterator<Object> iterator() {
10331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Iterators.emptyIterator();
10341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  };
10361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Queue that discards all elements.
10391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value
10411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <E> Queue<E> discardingQueue() {
10421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (Queue) DISCARDING_QUEUE;
10431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
10441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
10461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Note: All of this duplicate code sucks, but it saves a lot of memory. If only Java had mixins!
10471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * To maintain this code, make a change for the strong reference type. Then, cut and paste, and
10481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * replace "Strong" with "Soft" or "Weak" within the pasted text. The primary difference is that
10491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * strong entries store the key reference directly while soft and weak entries delegate to their
10501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * respective superclasses.
10511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
10541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Used for strongly-referenced keys.
10551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
10561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class StrongEntry<K, V> implements ReferenceEntry<K, V> {
10571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final K key;
10581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StrongEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
10601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.key = key;
10611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.hash = hash;
10621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.next = next;
10631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public K getKey() {
10671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this.key;
10681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // null access
10711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
10741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
10751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
10791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
10801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
10841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
10851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
10891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
10901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
10941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
10951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
10961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
10971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
10981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
10991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // null write
11031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
11061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
11111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
11161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
11211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
11261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
11311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
11321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each entry type.
11351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int hash;
11371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceEntry<K, V> next;
11381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile ValueReference<K, V> valueReference = unset();
11391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> getValueReference() {
11421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return valueReference;
11431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setValueReference(ValueReference<K, V> valueReference) {
11471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.valueReference = valueReference;
11481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getHash() {
11521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return hash;
11531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNext() {
11571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return next;
11581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
11601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class StrongAccessEntry<K, V> extends StrongEntry<K, V>
11621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      implements ReferenceEntry<K, V> {
11631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StrongAccessEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
11641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(key, hash, next);
11651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each access entry type.
11681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long accessTime = Long.MAX_VALUE;
11701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
11731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return accessTime;
11741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
11781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.accessTime = time;
11791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
11821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextAccess = nullEntry();
11831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
11861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextAccess;
11871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
11911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextAccess = next;
11921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
11931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
11951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousAccess = nullEntry();
11961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
11971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
11981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
11991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousAccess;
12001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
12041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousAccess = previous;
12051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
12071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class StrongWriteEntry<K, V>
12091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
12101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StrongWriteEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
12111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(key, hash, next);
12121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each write entry type.
12151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long writeTime = Long.MAX_VALUE;
12171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
12201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return writeTime;
12211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
12251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.writeTime = time;
12261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
12291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextWrite = nullEntry();
12301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
12331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextWrite;
12341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
12381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextWrite = next;
12391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
12421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousWrite = nullEntry();
12431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
12461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousWrite;
12471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
12511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousWrite = previous;
12521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
12541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class StrongAccessWriteEntry<K, V>
12561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
12571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StrongAccessWriteEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
12581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(key, hash, next);
12591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each access entry type.
12621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long accessTime = Long.MAX_VALUE;
12641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
12671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return accessTime;
12681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
12721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.accessTime = time;
12731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
12761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextAccess = nullEntry();
12771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
12801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextAccess;
12811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
12851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextAccess = next;
12861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
12891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousAccess = nullEntry();
12901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
12931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousAccess;
12941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
12951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
12961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
12971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
12981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousAccess = previous;
12991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each write entry type.
13021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long writeTime = Long.MAX_VALUE;
13041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
13071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return writeTime;
13081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
13121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.writeTime = time;
13131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
13161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextWrite = nullEntry();
13171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
13201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextWrite;
13211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
13251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextWrite = next;
13261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
13291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousWrite = nullEntry();
13301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
13331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousWrite;
13341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
13381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousWrite = previous;
13391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
13411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
13431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Used for weakly-referenced keys.
13441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
13451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class WeakEntry<K, V> extends WeakReference<K> implements ReferenceEntry<K, V> {
13461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeakEntry(ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
13471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(key, queue);
13481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.hash = hash;
13491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.next = next;
13501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public K getKey() {
13541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return get();
13551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // null access
13581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
13611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
13661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
13711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
13761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
13811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
13861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // null write
13901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
13931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
13951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
13961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
13971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
13981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
13991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
14031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
14041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
14081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
14091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
14131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
14141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
14181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
14191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each entry type.
14221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int hash;
14241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceEntry<K, V> next;
14251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile ValueReference<K, V> valueReference = unset();
14261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> getValueReference() {
14291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return valueReference;
14301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setValueReference(ValueReference<K, V> valueReference) {
14341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.valueReference = valueReference;
14351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getHash() {
14391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return hash;
14401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNext() {
14441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return next;
14451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
14471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WeakAccessEntry<K, V>
14491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
14501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeakAccessEntry(
14511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
14521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(queue, key, hash, next);
14531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each access entry type.
14561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long accessTime = Long.MAX_VALUE;
14581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
14611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return accessTime;
14621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
14661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.accessTime = time;
14671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
14701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextAccess = nullEntry();
14711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
14741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextAccess;
14751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
14791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextAccess = next;
14801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
14831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousAccess = nullEntry();
14841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
14871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousAccess;
14881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
14911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
14921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousAccess = previous;
14931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
14941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
14951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
14961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WeakWriteEntry<K, V>
14971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
14981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeakWriteEntry(
14991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
15001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(queue, key, hash, next);
15011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each write entry type.
15041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long writeTime = Long.MAX_VALUE;
15061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
15091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return writeTime;
15101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
15141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.writeTime = time;
15151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
15181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextWrite = nullEntry();
15191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
15221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextWrite;
15231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
15271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextWrite = next;
15281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
15311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousWrite = nullEntry();
15321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
15351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousWrite;
15361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
15401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousWrite = previous;
15411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
15431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WeakAccessWriteEntry<K, V>
15451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
15461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeakAccessWriteEntry(
15471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
15481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(queue, key, hash, next);
15491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each access entry type.
15521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long accessTime = Long.MAX_VALUE;
15541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getAccessTime() {
15571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return accessTime;
15581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setAccessTime(long time) {
15621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.accessTime = time;
15631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
15661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextAccess = nullEntry();
15671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInAccessQueue() {
15701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextAccess;
15711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
15751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextAccess = next;
15761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
15791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousAccess = nullEntry();
15801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInAccessQueue() {
15831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousAccess;
15841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
15881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousAccess = previous;
15891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // The code below is exactly the same for each write entry type.
15921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile long writeTime = Long.MAX_VALUE;
15941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
15951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
15961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long getWriteTime() {
15971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return writeTime;
15981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
15991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setWriteTime(long time) {
16021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.writeTime = time;
16031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
16061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextWrite = nullEntry();
16071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getNextInWriteQueue() {
16101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextWrite;
16111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
16151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.nextWrite = next;
16161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
16191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> previousWrite = nullEntry();
16201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getPreviousInWriteQueue() {
16231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return previousWrite;
16241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
16281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.previousWrite = previous;
16291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
16311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
16331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * References a weak value.
16341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
16351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class WeakValueReference<K, V>
16361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends WeakReference<V> implements ValueReference<K, V> {
16371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceEntry<K, V> entry;
16381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeakValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
16401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(referent, queue);
16411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.entry = entry;
16421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
16461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 1;
16471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
16511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return entry;
16521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void notifyNewValue(V newValue) {}
16561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(
16591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
16601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new WeakValueReference<K, V>(queue, get(), entry);
16611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isLoading() {
16651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
16661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isActive() {
16701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
16711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() {
16751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return get();
16761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
16781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
16801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * References a soft value.
16811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
16821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class SoftValueReference<K, V>
16831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends SoftReference<V> implements ValueReference<K, V> {
16841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceEntry<K, V> entry;
16851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SoftValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
16871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(referent, queue);
16881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.entry = entry;
16891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
16931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 1;
16941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
16951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
16961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
16971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
16981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return entry;
16991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void notifyNewValue(V newValue) {}
17031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
17061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new SoftValueReference<K, V>(queue, get(), entry);
17071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isLoading() {
17111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
17121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isActive() {
17161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
17171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() {
17211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return get();
17221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
17241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
17261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * References a strong value.
17271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
17281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class StrongValueReference<K, V> implements ValueReference<K, V> {
17291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final V referent;
17301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StrongValueReference(V referent) {
17321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.referent = referent;
17331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get() {
17371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return referent;
17381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
17421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 1;
17431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
17471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
17481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
17521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
17531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isLoading() {
17571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
17581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isActive() {
17621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
17631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() {
17671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return get();
17681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void notifyNewValue(V newValue) {}
17721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
17731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
17751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * References a weak value.
17761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
17771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WeightedWeakValueReference<K, V> extends WeakValueReference<K, V> {
17781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int weight;
17791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeightedWeakValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry,
17811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int weight) {
17821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(queue, referent, entry);
17831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.weight = weight;
17841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
17881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return weight;
17891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
17921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(
17931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
17941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new WeightedWeakValueReference<K, V>(queue, get(), entry, weight);
17951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
17961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
17971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
17981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
17991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * References a soft value.
18001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
18011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WeightedSoftValueReference<K, V> extends SoftValueReference<K, V> {
18021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int weight;
18031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeightedSoftValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry,
18051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int weight) {
18061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(queue, referent, entry);
18071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.weight = weight;
18081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
18091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
18111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
18121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return weight;
18131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
18141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
18151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
18161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new WeightedSoftValueReference<K, V>(queue, get(), entry, weight);
18171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
18181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
18221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * References a strong value.
18231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
18241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WeightedStrongValueReference<K, V> extends StrongValueReference<K, V> {
18251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int weight;
18261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WeightedStrongValueReference(V referent, int weight) {
18281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(referent);
18291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.weight = weight;
18301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
18311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
18331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
18341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return weight;
18351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
18361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
18391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Applies a supplemental hash function to a given hash code, which defends against poor quality
18401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * hash functions. This is critical when the concurrent hash map uses power-of-two length hash
18411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * tables, that otherwise encounter collisions for hash codes that do not differ in lower or
18421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * upper bits.
18431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
18441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param h hash code
18451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
18461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static int rehash(int h) {
18471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Spread bits to regularize both segment and index locations,
18481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // using variant of single-word Wang/Jenkins hash.
18491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(kevinb): use Hashing/move this to Hashing?
18501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    h += (h << 15) ^ 0xffffcd7d;
18511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    h ^= (h >>> 10);
18521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    h += (h << 3);
18531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    h ^= (h >>> 6);
18541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    h += (h << 2) + (h << 14);
18551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return h ^ (h >>> 16);
18561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
18591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method is a convenience for testing. Code should call {@link Segment#newEntry} directly.
18601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
18611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
18621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting
18631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
18641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).newEntry(key, hash, next);
18651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
18681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method is a convenience for testing. Code should call {@link Segment#copyEntry} directly.
18691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
18701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
18711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting
18721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ReferenceEntry<K, V> copyEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
18731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = original.getHash();
18741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).copyEntry(original, newNext);
18751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
18781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method is a convenience for testing. Code should call {@link Segment#setValue} instead.
18791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
18801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
18811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting
18821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ValueReference<K, V> newValueReference(ReferenceEntry<K, V> entry, V value, int weight) {
18831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = entry.getHash();
18841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return valueStrength.referenceValue(segmentFor(hash), entry, value, weight);
18851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  int hash(Object key) {
18881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int h = keyEquivalence.hash(key);
18891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return rehash(h);
18901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  void reclaimValue(ValueReference<K, V> valueReference) {
18931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> entry = valueReference.getEntry();
18941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = entry.getHash();
18951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference);
18961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
18971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
18981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  void reclaimKey(ReferenceEntry<K, V> entry) {
18991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = entry.getHash();
19001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    segmentFor(hash).reclaimKey(entry, hash);
19011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
19041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * This method is a convenience for testing. Code should call {@link Segment#getLiveValue}
19051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * instead.
19061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
19071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting
19081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean isLive(ReferenceEntry<K, V> entry, long now) {
19091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(entry.getHash()).getLiveValue(entry, now) != null;
19101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
19131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the segment that should be used for a key with the given hash.
19141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
19151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param hash the hash code for the key
19161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return the segment
19171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
19181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Segment<K, V> segmentFor(int hash) {
19191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(fry): Lazily create segments?
19201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segments[(hash >>> segmentShift) & segmentMask];
19211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Segment<K, V> createSegment(
19241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int initialCapacity, long maxSegmentWeight, StatsCounter statsCounter) {
19251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new Segment<K, V>(this, initialCapacity, maxSegmentWeight, statsCounter);
19261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
19291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Gets the value from an entry. Returns null if the entry is invalid, partially-collected,
19301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * loading, or expired. Unlike {@link Segment#getLiveValue} this method does not attempt to
19311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * cleanup stale entries. As such it should only be called outside of a segment context, such as
19321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * during iteration.
19331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
19341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
19351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  V getLiveValue(ReferenceEntry<K, V> entry, long now) {
19361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (entry.getKey() == null) {
19371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
19381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
19391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V value = entry.getValueReference().get();
19401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (value == null) {
19411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
19421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
19431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (isExpired(entry, now)) {
19451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
19461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
19471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return value;
19481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // expiration
19511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
19531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns true if the entry has expired.
19541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
19551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean isExpired(ReferenceEntry<K, V> entry, long now) {
19561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (expiresAfterAccess()
19571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        && (now - entry.getAccessTime() > expireAfterAccessNanos)) {
19581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
19591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
19601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (expiresAfterWrite()
19611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        && (now - entry.getWriteTime() > expireAfterWriteNanos)) {
19621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
19631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
19641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
19651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // queues
19681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
19701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <K, V> void connectAccessOrder(ReferenceEntry<K, V> previous, ReferenceEntry<K, V> next) {
19711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    previous.setNextInAccessQueue(next);
19721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    next.setPreviousInAccessQueue(previous);
19731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
19761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <K, V> void nullifyAccessOrder(ReferenceEntry<K, V> nulled) {
19771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nullEntry = nullEntry();
19781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    nulled.setNextInAccessQueue(nullEntry);
19791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    nulled.setPreviousInAccessQueue(nullEntry);
19801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
19831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <K, V> void connectWriteOrder(ReferenceEntry<K, V> previous, ReferenceEntry<K, V> next) {
19841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    previous.setNextInWriteQueue(next);
19851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    next.setPreviousInWriteQueue(previous);
19861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GuardedBy("Segment.this")
19891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <K, V> void nullifyWriteOrder(ReferenceEntry<K, V> nulled) {
19901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nullEntry = nullEntry();
19911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    nulled.setNextInWriteQueue(nullEntry);
19921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    nulled.setPreviousInWriteQueue(nullEntry);
19931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
19941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
19951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
19961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Notifies listeners that an entry has been automatically removed due to expiration, eviction,
19971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * or eligibility for garbage collection. This should be called every time expireEntries or
19981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * evictEntry is called (once the lock is released).
19991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
20001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  void processPendingNotifications() {
20011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    RemovalNotification<K, V> notification;
20021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    while ((notification = removalNotificationQueue.poll()) != null) {
20031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
20041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        removalListener.onRemoval(notification);
20051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (Throwable e) {
20061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        logger.log(Level.WARNING, "Exception thrown by removal listener", e);
20071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
20081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
20091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
20101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked")
20121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final Segment<K, V>[] newSegmentArray(int ssize) {
20131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new Segment[ssize];
20141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
20151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Inner Classes
20171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
20191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Segments are specialized versions of hash tables. This subclass inherits from ReentrantLock
20201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * opportunistically, just to simplify some locking and avoid separate construction.
20211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
20221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("serial") // This class is never serialized.
20231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class Segment<K, V> extends ReentrantLock {
20241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
20261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * TODO(fry): Consider copying variables (like evictsBySize) from outer class into this class.
20271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * It will require more memory but will reduce indirection.
20281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
20311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Segments maintain a table of entry lists that are ALWAYS kept in a consistent state, so can
20321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * be read without locking. Next fields of nodes are immutable (final). All list additions are
20331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * performed at the front of each bin. This makes it easy to check changes, and also fast to
20341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * traverse. When nodes would otherwise be changed, new nodes are created to replace them. This
20351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * works well for hash tables since the bin lists tend to be short. (The average length is less
20361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * than two.)
20371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
20381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Read operations can thus proceed without locking, but rely on selected uses of volatiles to
20391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * ensure that completed write operations performed by other threads are noticed. For most
20401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * purposes, the "count" field, tracking the number of elements, serves as that volatile
20411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * variable ensuring visibility. This is convenient because this field needs to be read in many
20421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * read operations anyway:
20431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
20441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * - All (unsynchronized) read operations must first read the "count" field, and should not
20451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * look at table entries if it is 0.
20461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
20471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * - All (synchronized) write operations should write to the "count" field after structurally
20481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * changing any bin. The operations must not take any action that could even momentarily
20491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * cause a concurrent read operation to see inconsistent data. This is made easier by the
20501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * nature of the read operations in Map. For example, no operation can reveal that the table
20511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * has grown but the threshold has not yet been updated, so there are no atomicity requirements
20521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * for this with respect to reads.
20531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
20541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * As a guide, all critical volatile reads and writes to the count field are marked in code
20551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * comments.
20561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final LocalCache<K, V> map;
20591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The number of live elements in this segment's region.
20621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile int count;
20641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The weight of the live elements in this segment's region.
20671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
20691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int totalWeight;
20701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Number of updates that alter the size of the table. This is used during bulk-read methods to
20731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * make sure they see a consistent snapshot: If modCounts change during a traversal of segments
20741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * loading size or checking containsValue, then we might have an inconsistent view of state
20751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * so (usually) must retry.
20761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int modCount;
20781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The table is expanded when its size exceeds this threshold. (The value of this field is
20811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * always {@code (int)(capacity * 0.75)}.)
20821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int threshold;
20841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The per-segment table.
20871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile AtomicReferenceArray<ReferenceEntry<K, V>> table;
20891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The maximum weight of this segment. UNSET_INT if there is no maximum.
20921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final long maxSegmentWeight;
20941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
20951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
20961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The key reference queue contains entries whose keys have been garbage collected, and which
20971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * need to be cleaned up internally.
20981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
20991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceQueue<K> keyReferenceQueue;
21001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
21021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The value reference queue contains value references whose values have been garbage collected,
21031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * and which need to be cleaned up internally.
21041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
21051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceQueue<V> valueReferenceQueue;
21061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
21081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * The recency queue is used to record which entries were accessed for updating the access
21091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * list's ordering. It is drained as a batch operation when either the DRAIN_THRESHOLD is
21101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * crossed or a write occurs on the segment.
21111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
21121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Queue<ReferenceEntry<K, V>> recencyQueue;
21131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
21151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * A counter of the number of reads since the last write, used to drain queues on a small
21161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * fraction of read operations.
21171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
21181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final AtomicInteger readCount = new AtomicInteger();
21191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
21211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * A queue of elements currently in the map, ordered by write time. Elements are added to the
21221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * tail of the queue on write.
21231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
21241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
21251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Queue<ReferenceEntry<K, V>> writeQueue;
21261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
21281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * A queue of elements currently in the map, ordered by access time. Elements are added to the
21291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * tail of the queue on access (note that writes count as accesses).
21301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
21311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
21321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Queue<ReferenceEntry<K, V>> accessQueue;
21331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /** Accumulates cache statistics. */
21351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final StatsCounter statsCounter;
21361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Segment(LocalCache<K, V> map, int initialCapacity, long maxSegmentWeight,
21381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        StatsCounter statsCounter) {
21391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.map = map;
21401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.maxSegmentWeight = maxSegmentWeight;
21411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.statsCounter = statsCounter;
21421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      initTable(newEntryArray(initialCapacity));
21431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      keyReferenceQueue = map.usesKeyReferences()
21451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert           ? new ReferenceQueue<K>() : null;
21461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      valueReferenceQueue = map.usesValueReferences()
21481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert           ? new ReferenceQueue<V>() : null;
21491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      recencyQueue = map.usesAccessQueue()
21511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ? new ConcurrentLinkedQueue<ReferenceEntry<K, V>>()
21521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          : LocalCache.<ReferenceEntry<K, V>>discardingQueue();
21531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      writeQueue = map.usesWriteQueue()
21551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ? new WriteQueue<K, V>()
21561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          : LocalCache.<ReferenceEntry<K, V>>discardingQueue();
21571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      accessQueue = map.usesAccessQueue()
21591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ? new AccessQueue<K, V>()
21601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          : LocalCache.<ReferenceEntry<K, V>>discardingQueue();
21611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
21621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicReferenceArray<ReferenceEntry<K, V>> newEntryArray(int size) {
21641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new AtomicReferenceArray<ReferenceEntry<K, V>>(size);
21651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
21661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void initTable(AtomicReferenceArray<ReferenceEntry<K, V>> newTable) {
21681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.threshold = newTable.length() * 3 / 4; // 0.75
21691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!map.customWeigher() && this.threshold == maxSegmentWeight) {
21701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // prevent spurious expansion before eviction
21711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.threshold++;
21721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
21731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.table = newTable;
21741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
21751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
21771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
21781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return map.entryFactory.newEntry(this, key, hash, next);
21791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
21801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
21821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> copyEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
21831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ValueReference<K, V> valueReference = original.getValueReference();
21841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> newEntry = map.entryFactory.copyEntry(this, original, newNext);
21851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      newEntry.setValueReference(valueReference.copyFor(this.valueReferenceQueue, newEntry));
21861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return newEntry;
21871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
21881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
21901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sets a new value of an entry. Adds newly created entries at the end of the access queue.
21911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
21921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
21931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void setValue(ReferenceEntry<K, V> entry, K key, V value, long now) {
21941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ValueReference<K, V> previous = entry.getValueReference();
21951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int weight = map.weigher.weigh(key, value);
21961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkState(weight >= 0, "Weights must be non-negative");
21971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
21981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ValueReference<K, V> valueReference =
21991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          map.valueStrength.referenceValue(this, entry, value, weight);
22001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      entry.setValueReference(valueReference);
22011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      recordWrite(entry, weight, now);
22021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      previous.notifyNewValue(value);
22031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
22041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // loading
22061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {
22081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
22091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (count != 0) { // read-volatile
22101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't call getLiveEntry, which would ignore loading values
22111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> e = getEntry(key, hash);
22121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e != null) {
22131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            long now = map.ticker.read();
22141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V value = getLiveValue(e, now);
22151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (value != null) {
22161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              recordRead(e, now);
22171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              statsCounter.recordHits(1);
22181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return scheduleRefresh(e, key, hash, value, now, loader);
22191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
22201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
22211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (valueReference.isLoading()) {
22221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return waitForLoadingValue(e, key, valueReference);
22231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
22241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
22251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
22261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // at this point e is either null or expired;
22281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return lockedGetOrLoad(key, hash, loader);
22291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (ExecutionException ee) {
22301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Throwable cause = ee.getCause();
22311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (cause instanceof Error) {
22321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new ExecutionError((Error) cause);
22331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else if (cause instanceof RuntimeException) {
22341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new UncheckedExecutionException(cause);
22351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
22361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw ee;
22371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
22381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postReadCleanup();
22391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
22401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
22411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V lockedGetOrLoad(K key, int hash, CacheLoader<? super K, V> loader)
22431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throws ExecutionException {
22441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e;
22451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ValueReference<K, V> valueReference = null;
22461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      LoadingValueReference<K, V> loadingValueReference = null;
22471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean createNewEntry = true;
22481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
22501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
22511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // re-read ticker once inside the lock
22521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
22531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
22541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = this.count - 1;
22561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
22571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
22581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
22591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (e = first; e != null; e = e.getNext()) {
22611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
22621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
22631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
22641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            valueReference = e.getValueReference();
22651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (valueReference.isLoading()) {
22661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              createNewEntry = false;
22671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
22681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              V value = valueReference.get();
22691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (value == null) {
22701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                enqueueNotification(entryKey, hash, valueReference, RemovalCause.COLLECTED);
22711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } else if (map.isExpired(e, now)) {
22721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // This is a duplicate check, as preWriteCleanup already purged expired
22731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // entries, but let's accomodate an incorrect expiration queue.
22741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                enqueueNotification(entryKey, hash, valueReference, RemovalCause.EXPIRED);
22751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } else {
22761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                recordLockedRead(e, now);
22771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                statsCounter.recordHits(1);
22781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // we were concurrent with loading; don't consider refresh
22791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                return value;
22801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
22811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // immediately reuse invalid entries
22831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              writeQueue.remove(e);
22841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              accessQueue.remove(e);
22851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              this.count = newCount; // write-volatile
22861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
22871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            break;
22881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
22891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
22901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (createNewEntry) {
22921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          loadingValueReference = new LoadingValueReference<K, V>();
22931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
22941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e == null) {
22951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            e = newEntry(key, hash, first);
22961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            e.setValueReference(loadingValueReference);
22971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            table.set(index, e);
22981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } else {
22991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            e.setValueReference(loadingValueReference);
23001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
23011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
23021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
23031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
23041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
23051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
23061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (createNewEntry) {
23081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
23091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // Synchronizes on the entry to allow failing fast when a recursive load is
23101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // detected. This may be circumvented when an entry is copied, but will fail fast most
23111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // of the time.
23121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          synchronized (e) {
23131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return loadSync(key, hash, loadingValueReference, loader);
23141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
23151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
23161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          statsCounter.recordMisses(1);
23171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
23181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
23191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // The entry already exists. Wait for loading.
23201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return waitForLoadingValue(e, key, valueReference);
23211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
23221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
23231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V waitForLoadingValue(ReferenceEntry<K, V> e, K key, ValueReference<K, V> valueReference)
23251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throws ExecutionException {
23261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!valueReference.isLoading()) {
23271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new AssertionError();
23281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
23291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkState(!Thread.holdsLock(e), "Recursive load");
23311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // don't consider expiration as we're concurrent with loading
23321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
23331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V value = valueReference.waitForValue();
23341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value == null) {
23351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new InvalidCacheLoadException("CacheLoader returned null for key " + key + ".");
23361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
23371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // re-read ticker now that loading has completed
23381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
23391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        recordRead(e, now);
23401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return value;
23411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
23421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        statsCounter.recordMisses(1);
23431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
23441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
23451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // at most one of loadSync/loadAsync may be called for any given LoadingValueReference
23471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V loadSync(K key, int hash, LoadingValueReference<K, V> loadingValueReference,
23491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        CacheLoader<? super K, V> loader) throws ExecutionException {
23501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ListenableFuture<V> loadingFuture = loadingValueReference.loadFuture(key, loader);
23511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
23521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
23531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ListenableFuture<V> loadAsync(final K key, final int hash,
23551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        final LoadingValueReference<K, V> loadingValueReference, CacheLoader<? super K, V> loader) {
23561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final ListenableFuture<V> loadingFuture = loadingValueReference.loadFuture(key, loader);
23571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      loadingFuture.addListener(
23581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          new Runnable() {
23591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @Override
23601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            public void run() {
23611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              try {
23621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                V newValue = getAndRecordStats(key, hash, loadingValueReference, loadingFuture);
23631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // update loadingFuture for the sake of other pending requests
23641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                loadingValueReference.set(newValue);
23651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } catch (Throwable t) {
23661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                logger.log(Level.WARNING, "Exception thrown during refresh", t);
23671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                loadingValueReference.setException(t);
23681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
23691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
23701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }, sameThreadExecutor);
23711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return loadingFuture;
23721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
23731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
23751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Waits uninterruptibly for {@code newValue} to be loaded, and then records loading stats.
23761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
23771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V getAndRecordStats(K key, int hash, LoadingValueReference<K, V> loadingValueReference,
23781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ListenableFuture<V> newValue) throws ExecutionException {
23791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value = null;
23801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
23811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        value = getUninterruptibly(newValue);
23821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value == null) {
23831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new InvalidCacheLoadException("CacheLoader returned null for key " + key + ".");
23841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
23851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        statsCounter.recordLoadSuccess(loadingValueReference.elapsedNanos());
23861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        storeLoadedValue(key, hash, loadingValueReference, value);
23871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return value;
23881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
23891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value == null) {
23901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          statsCounter.recordLoadException(loadingValueReference.elapsedNanos());
23911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          removeLoadingValue(key, hash, loadingValueReference);
23921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
23931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
23941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
23951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
23961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V scheduleRefresh(ReferenceEntry<K, V> entry, K key, int hash, V oldValue, long now,
23971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        CacheLoader<? super K, V> loader) {
23981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.refreshes() && (now - entry.getWriteTime() > map.refreshNanos)) {
23991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V newValue = refresh(key, hash, loader);
24001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (newValue != null) {
24011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return newValue;
24021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
24031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
24041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return oldValue;
24051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
24061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
24081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Refreshes the value associated with {@code key}, unless another thread is already doing so.
24091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns the newly refreshed value associated with {@code key} if it was refreshed inline, or
24101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * {@code null} if another thread is performing the refresh or if an error occurs during
24111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * refresh.
24121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
24131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
24141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V refresh(K key, int hash, CacheLoader<? super K, V> loader) {
24151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final LoadingValueReference<K, V> loadingValueReference =
24161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          insertLoadingValueReference(key, hash);
24171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (loadingValueReference == null) {
24181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
24191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
24201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ListenableFuture<V> result = loadAsync(key, hash, loadingValueReference, loader);
24221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (result.isDone()) {
24231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
24241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return result.get();
24251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (Throwable t) {
24261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't let refresh exceptions propagate; error was already logged
24271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
24281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
24291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
24301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
24311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
24331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns a newly inserted {@code LoadingValueReference}, or null if the live value reference
24341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * is already loading.
24351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
24361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
24371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingValueReference<K, V> insertLoadingValueReference(final K key, final int hash) {
24381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = null;
24391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
24401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
24411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
24421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
24431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
24451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
24461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
24471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // Look for an existing entry.
24491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (e = first; e != null; e = e.getNext()) {
24501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
24511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
24521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
24531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // We found an existing entry.
24541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
24561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (valueReference.isLoading()) {
24571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // refresh is a no-op if loading is pending
24581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return null;
24591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
24601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // continue returning old value while loading
24621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ++modCount;
24631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            LoadingValueReference<K, V> loadingValueReference =
24641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                new LoadingValueReference<K, V>(valueReference);
24651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            e.setValueReference(loadingValueReference);
24661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return loadingValueReference;
24671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
24681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
24691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ++modCount;
24711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        LoadingValueReference<K, V> loadingValueReference = new LoadingValueReference<K, V>();
24721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        e = newEntry(key, hash, first);
24731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        e.setValueReference(loadingValueReference);
24741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        table.set(index, e);
24751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return loadingValueReference;
24761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
24771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
24781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
24791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
24801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
24811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // reference queues, for garbage collection cleanup
24831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
24851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Cleanup collected entries when the lock is available.
24861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
24871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void tryDrainReferenceQueues() {
24881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (tryLock()) {
24891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
24901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          drainReferenceQueues();
24911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
24921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          unlock();
24931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
24941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
24951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
24961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
24971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
24981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Drain the key and value reference queues, cleaning up internal entries containing garbage
24991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * collected keys or values.
25001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
25011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
25021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void drainReferenceQueues() {
25031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.usesKeyReferences()) {
25041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        drainKeyReferenceQueue();
25051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.usesValueReferences()) {
25071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        drainValueReferenceQueue();
25081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
25121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void drainKeyReferenceQueue() {
25131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Reference<? extends K> ref;
25141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int i = 0;
25151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while ((ref = keyReferenceQueue.poll()) != null) {
25161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @SuppressWarnings("unchecked")
25171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> entry = (ReferenceEntry<K, V>) ref;
25181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        map.reclaimKey(entry);
25191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (++i == DRAIN_MAX) {
25201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          break;
25211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
25221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
25261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void drainValueReferenceQueue() {
25271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Reference<? extends V> ref;
25281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int i = 0;
25291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while ((ref = valueReferenceQueue.poll()) != null) {
25301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @SuppressWarnings("unchecked")
25311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ValueReference<K, V> valueReference = (ValueReference<K, V>) ref;
25321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        map.reclaimValue(valueReference);
25331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (++i == DRAIN_MAX) {
25341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          break;
25351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
25361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
25401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Clears all entries from the key and value reference queues.
25411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
25421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void clearReferenceQueues() {
25431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.usesKeyReferences()) {
25441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        clearKeyReferenceQueue();
25451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.usesValueReferences()) {
25471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        clearValueReferenceQueue();
25481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void clearKeyReferenceQueue() {
25521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (keyReferenceQueue.poll() != null) {}
25531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void clearValueReferenceQueue() {
25561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (valueReferenceQueue.poll() != null) {}
25571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // recency queue, shared by expiration and eviction
25601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
25621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Records the relative order in which this read was performed by adding {@code entry} to the
25631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * recency queue. At write-time, or when the queue is full past the threshold, the queue will
25641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * be drained and the entries therein processed.
25651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
25661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * <p>Note: locked reads should use {@link #recordLockedRead}.
25671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
25681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void recordRead(ReferenceEntry<K, V> entry, long now) {
25691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.recordsAccess()) {
25701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        entry.setAccessTime(now);
25711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      recencyQueue.add(entry);
25731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
25761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Updates the eviction metadata that {@code entry} was just read. This currently amounts to
25771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * adding {@code entry} to relevant eviction lists.
25781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
25791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * <p>Note: this method should only be called under lock, as it directly manipulates the
25801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * eviction queues. Unlocked reads should use {@link #recordRead}.
25811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
25821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
25831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void recordLockedRead(ReferenceEntry<K, V> entry, long now) {
25841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.recordsAccess()) {
25851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        entry.setAccessTime(now);
25861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
25871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      accessQueue.add(entry);
25881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
25891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
25901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
25911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Updates eviction metadata that {@code entry} was just written. This currently amounts to
25921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * adding {@code entry} to relevant eviction lists.
25931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
25941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
25951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void recordWrite(ReferenceEntry<K, V> entry, int weight, long now) {
25961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // we are already under lock, so drain the recency queue immediately
25971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      drainRecencyQueue();
25981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      totalWeight += weight;
25991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.recordsAccess()) {
26011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        entry.setAccessTime(now);
26021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.recordsWrite()) {
26041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        entry.setWriteTime(now);
26051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      accessQueue.add(entry);
26071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      writeQueue.add(entry);
26081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
26091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
26111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Drains the recency queue, updating eviction metadata that the entries therein were read in
26121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * the specified relative order. This currently amounts to adding them to relevant eviction
26131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * lists (accounting for the fact that they could have been removed from the map since being
26141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * added to the recency queue).
26151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
26161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
26171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void drainRecencyQueue() {
26181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e;
26191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while ((e = recencyQueue.poll()) != null) {
26201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // An entry may be in the recency queue despite it being removed from
26211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // the map . This can occur when the entry was concurrently read while a
26221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // writer is removing it from the segment or after a clear has removed
26231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // all of the segment's entries.
26241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (accessQueue.contains(e)) {
26251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          accessQueue.add(e);
26261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
26271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
26291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // expiration
26311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
26331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Cleanup expired entries when the lock is available.
26341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
26351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void tryExpireEntries(long now) {
26361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (tryLock()) {
26371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
26381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          expireEntries(now);
26391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
26401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          unlock();
26411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // don't call postWriteCleanup as we're in a read
26421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
26431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
26451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
26471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void expireEntries(long now) {
26481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      drainRecencyQueue();
26491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e;
26511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while ((e = writeQueue.peek()) != null && map.isExpired(e, now)) {
26521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) {
26531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
26541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
26551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while ((e = accessQueue.peek()) != null && map.isExpired(e, now)) {
26571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) {
26581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
26591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
26601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
26621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // eviction
26641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
26661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void enqueueNotification(ReferenceEntry<K, V> entry, RemovalCause cause) {
26671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference(), cause);
26681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
26691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
26711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void enqueueNotification(@Nullable K key, int hash, ValueReference<K, V> valueReference,
26721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        RemovalCause cause) {
26731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      totalWeight -= valueReference.getWeight();
26741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (cause.wasEvicted()) {
26751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        statsCounter.recordEviction();
26761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.removalNotificationQueue != DISCARDING_QUEUE) {
26781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V value = valueReference.get();
26791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        RemovalNotification<K, V> notification = new RemovalNotification<K, V>(key, value, cause);
26801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        map.removalNotificationQueue.offer(notification);
26811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
26831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
26851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Performs eviction if the segment is full. This should only be called prior to adding a new
26861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * entry and increasing {@code count}.
26871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
26881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
26891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void evictEntries() {
26901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!map.evictsBySize()) {
26911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return;
26921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
26931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
26941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      drainRecencyQueue();
26951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (totalWeight > maxSegmentWeight) {
26961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> e = getNextEvictable();
26971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (!removeEntry(e, e.getHash(), RemovalCause.SIZE)) {
26981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
26991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
27001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
27021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(fry): instead implement this with an eviction head
27041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getNextEvictable() {
27051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (ReferenceEntry<K, V> e : accessQueue) {
27061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int weight = e.getValueReference().getWeight();
27071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (weight > 0) {
27081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return e;
27091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
27101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError();
27121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
27131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
27151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns first entry of bin for given hash.
27161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
27171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getFirst(int hash) {
27181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // read this volatile field only once
27191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
27201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return table.get(hash & (table.length() - 1));
27211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
27221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Specialized implementations of map methods
27241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
27261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getEntry(Object key, int hash) {
27271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (ReferenceEntry<K, V> e = getFirst(hash); e != null; e = e.getNext()) {
27281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (e.getHash() != hash) {
27291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue;
27301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
27311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        K entryKey = e.getKey();
27331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (entryKey == null) {
27341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          tryDrainReferenceQueues();
27351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          continue;
27361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
27371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (map.keyEquivalence.equivalent(key, entryKey)) {
27391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return e;
27401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
27411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
27441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
27451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
27471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> getLiveEntry(Object key, int hash, long now) {
27481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = getEntry(key, hash);
27491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (e == null) {
27501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
27511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else if (map.isExpired(e, now)) {
27521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        tryExpireEntries(now);
27531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
27541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return e;
27561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
27571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
27591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Gets the value from an entry. Returns null if the entry is invalid, partially-collected,
27601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * loading, or expired.
27611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
27621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V getLiveValue(ReferenceEntry<K, V> entry, long now) {
27631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (entry.getKey() == null) {
27641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        tryDrainReferenceQueues();
27651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
27661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value = entry.getValueReference().get();
27681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (value == null) {
27691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        tryDrainReferenceQueues();
27701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
27711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (map.isExpired(entry, now)) {
27741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        tryExpireEntries(now);
27751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
27761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
27771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return value;
27781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
27791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
27811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V get(Object key, int hash) {
27821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
27831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (count != 0) { // read-volatile
27841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          long now = map.ticker.read();
27851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> e = getLiveEntry(key, hash, now);
27861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e == null) {
27871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return null;
27881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
27891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
27901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V value = e.getValueReference().get();
27911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (value != null) {
27921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            recordRead(e, now);
27931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return scheduleRefresh(e, e.getKey(), hash, value, now, map.defaultLoader);
27941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
27951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          tryDrainReferenceQueues();
27961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
27971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
27981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
27991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postReadCleanup();
28001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
28011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
28021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean containsKey(Object key, int hash) {
28041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
28051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (count != 0) { // read-volatile
28061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          long now = map.ticker.read();
28071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> e = getLiveEntry(key, hash, now);
28081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e == null) {
28091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return false;
28101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
28111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return e.getValueReference().get() != null;
28121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
28131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
28151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
28161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postReadCleanup();
28171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
28181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
28191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
28211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * This method is a convenience for testing. Code should call {@link
28221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * LocalCache#containsValue} directly.
28231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
28241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @VisibleForTesting
28251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean containsValue(Object value) {
28261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
28271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (count != 0) { // read-volatile
28281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          long now = map.ticker.read();
28291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
28301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          int length = table.length();
28311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (int i = 0; i < length; ++i) {
28321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) {
28331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              V entryValue = getLiveValue(e, now);
28341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (entryValue == null) {
28351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                continue;
28361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
28371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (map.valueEquivalence.equivalent(value, entryValue)) {
28381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                return true;
28391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
28401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
28411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
28421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
28431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
28451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
28461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postReadCleanup();
28471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
28481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
28491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
28511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V put(K key, int hash, V value, boolean onlyIfAbsent) {
28521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
28531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
28541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
28551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
28561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = this.count + 1;
28581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (newCount > this.threshold) { // ensure capacity
28591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          expand();
28601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          newCount = this.count + 1;
28611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
28621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
28641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
28651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
28661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // Look for an existing entry.
28681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
28691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
28701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
28711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
28721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // We found an existing entry.
28731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
28751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V entryValue = valueReference.get();
28761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
28771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (entryValue == null) {
28781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ++modCount;
28791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (valueReference.isActive()) {
28801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                enqueueNotification(key, hash, valueReference, RemovalCause.COLLECTED);
28811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                setValue(e, key, value, now);
28821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newCount = this.count; // count remains unchanged
28831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } else {
28841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                setValue(e, key, value, now);
28851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newCount = this.count + 1;
28861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
28871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              this.count = newCount; // write-volatile
28881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              evictEntries();
28891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return null;
28901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (onlyIfAbsent) {
28911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // Mimic
28921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // "if (!map.containsKey(key)) ...
28931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // else return map.get(key);
28941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              recordLockedRead(e, now);
28951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return entryValue;
28961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
28971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // clobber existing entry, count remains unchanged
28981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ++modCount;
28991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
29001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              setValue(e, key, value, now);
29011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              evictEntries();
29021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return entryValue;
29031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
29041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
29051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
29061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // Create a new entry.
29081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ++modCount;
29091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
29101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        setValue(newEntry, key, value, now);
29111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        table.set(index, newEntry);
29121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        newCount = this.count + 1;
29131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.count = newCount; // write-volatile
29141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        evictEntries();
29151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
29161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
29171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
29181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
29191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
29201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
29211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
29231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Expands the table if possible.
29241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
29251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
29261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void expand() {
29271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicReferenceArray<ReferenceEntry<K, V>> oldTable = table;
29281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int oldCapacity = oldTable.length();
29291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (oldCapacity >= MAXIMUM_CAPACITY) {
29301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return;
29311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
29321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      /*
29341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * Reclassify nodes in each list to new Map. Because we are using power-of-two expansion, the
29351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * elements from each bin must either stay at same index, or move with a power of two offset.
29361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * We eliminate unnecessary node creation by catching cases where old nodes can be reused
29371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * because their next fields won't change. Statistically, at the default threshold, only
29381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * about one-sixth of them need cloning when a table doubles. The nodes they replace will be
29391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * garbage collectable as soon as they are no longer referenced by any reader thread that may
29401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       * be in the midst of traversing table right now.
29411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert       */
29421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int newCount = count;
29441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicReferenceArray<ReferenceEntry<K, V>> newTable = newEntryArray(oldCapacity << 1);
29451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      threshold = newTable.length() * 3 / 4;
29461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int newMask = newTable.length() - 1;
29471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) {
29481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // We need to guarantee that any existing reads of old Map can
29491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // proceed. So we cannot yet null out each bin.
29501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> head = oldTable.get(oldIndex);
29511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (head != null) {
29531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> next = head.getNext();
29541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          int headIndex = head.getHash() & newMask;
29551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // Single node on list
29571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (next == null) {
29581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            newTable.set(headIndex, head);
29591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          } else {
29601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // Reuse the consecutive sequence of nodes with the same target
29611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // index from the end of the list. tail points to the first
29621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // entry in the reusable list.
29631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ReferenceEntry<K, V> tail = head;
29641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            int tailIndex = headIndex;
29651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            for (ReferenceEntry<K, V> e = next; e != null; e = e.getNext()) {
29661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              int newIndex = e.getHash() & newMask;
29671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (newIndex != tailIndex) {
29681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // The index changed. We'll need to copy the previous entry.
29691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                tailIndex = newIndex;
29701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                tail = e;
29711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
29721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
29731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            newTable.set(tailIndex, tail);
29741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // Clone nodes leading up to the tail.
29761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            for (ReferenceEntry<K, V> e = head; e != tail; e = e.getNext()) {
29771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (isCollected(e)) {
29781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                removeCollectedEntry(e);
29791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newCount--;
29801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } else {
29811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                int newIndex = e.getHash() & newMask;
29821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ReferenceEntry<K, V> newNext = newTable.get(newIndex);
29831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ReferenceEntry<K, V> newFirst = copyEntry(e, newNext);
29841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newTable.set(newIndex, newFirst);
29851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
29861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
29871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
29881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
29891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
29901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      table = newTable;
29911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.count = newCount;
29921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
29931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
29941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean replace(K key, int hash, V oldValue, V newValue) {
29951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
29961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
29971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
29981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
29991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
30011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
30021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
30031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
30051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
30061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
30071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
30081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
30091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V entryValue = valueReference.get();
30101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (entryValue == null) {
30111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (valueReference.isActive()) {
30121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // If the value disappeared, this entry is partially collected.
30131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                int newCount = this.count - 1;
30141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ++modCount;
30151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ReferenceEntry<K, V> newFirst = removeValueFromChain(
30161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED);
30171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newCount = this.count - 1;
30181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                table.set(index, newFirst);
30191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                this.count = newCount; // write-volatile
30201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
30211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return false;
30221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
30231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (map.valueEquivalence.equivalent(oldValue, entryValue)) {
30251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ++modCount;
30261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
30271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              setValue(e, key, newValue, now);
30281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              evictEntries();
30291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return true;
30301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
30311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // Mimic
30321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // "if (map.containsKey(key) && map.get(key).equals(oldValue))..."
30331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              recordLockedRead(e, now);
30341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return false;
30351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
30361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
30371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
30381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
30401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
30411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
30421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
30431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
30441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
30451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
30471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V replace(K key, int hash, V newValue) {
30481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
30491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
30501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
30511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
30521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
30541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
30551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
30561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
30581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
30591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
30601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
30611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
30621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V entryValue = valueReference.get();
30631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (entryValue == null) {
30641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (valueReference.isActive()) {
30651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                // If the value disappeared, this entry is partially collected.
30661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                int newCount = this.count - 1;
30671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ++modCount;
30681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ReferenceEntry<K, V> newFirst = removeValueFromChain(
30691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED);
30701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newCount = this.count - 1;
30711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                table.set(index, newFirst);
30721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                this.count = newCount; // write-volatile
30731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
30741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return null;
30751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
30761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ++modCount;
30781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
30791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            setValue(e, key, newValue, now);
30801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            evictEntries();
30811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return entryValue;
30821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
30831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
30841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
30861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
30871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
30881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
30891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
30901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
30911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
30931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V remove(Object key, int hash) {
30941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
30951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
30961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
30971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
30981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
30991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = this.count - 1;
31001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
31011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
31021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
31031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
31051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
31061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
31071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
31081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
31091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V entryValue = valueReference.get();
31101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            RemovalCause cause;
31121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (entryValue != null) {
31131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              cause = RemovalCause.EXPLICIT;
31141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (valueReference.isActive()) {
31151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              cause = RemovalCause.COLLECTED;
31161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
31171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // currently loading
31181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return null;
31191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
31201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ++modCount;
31221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ReferenceEntry<K, V> newFirst = removeValueFromChain(
31231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                first, e, entryKey, hash, valueReference, cause);
31241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            newCount = this.count - 1;
31251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            table.set(index, newFirst);
31261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            this.count = newCount; // write-volatile
31271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return entryValue;
31281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
31291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
31301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
31321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
31331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
31341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
31351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
31361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
31371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean storeLoadedValue(K key, int hash, LoadingValueReference<K, V> oldValueReference,
31391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V newValue) {
31401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
31411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
31421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
31431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
31441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = this.count + 1;
31461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
31471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
31481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
31491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
31511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
31521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
31531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
31541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
31551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V entryValue = valueReference.get();
31561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (entryValue == null || oldValueReference == valueReference) {
31571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ++modCount;
31581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (oldValueReference.isActive()) {
31591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                RemovalCause cause =
31601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                    (entryValue == null) ? RemovalCause.COLLECTED : RemovalCause.REPLACED;
31611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                enqueueNotification(key, hash, oldValueReference, cause);
31621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                newCount--;
31631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
31641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              setValue(e, key, newValue, now);
31651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              this.count = newCount; // write-volatile
31661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              evictEntries();
31671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return true;
31681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
31691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            // the loaded value was already clobbered
31711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            valueReference = new WeightedStrongValueReference<K, V>(newValue, 0);
31721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            enqueueNotification(key, hash, valueReference, RemovalCause.REPLACED);
31731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return false;
31741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
31751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
31761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ++modCount;
31781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
31791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        setValue(newEntry, key, newValue, now);
31801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        table.set(index, newEntry);
31811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.count = newCount; // write-volatile
31821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        evictEntries();
31831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return true;
31841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
31851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
31861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
31871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
31881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
31891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean remove(Object key, int hash, Object value) {
31911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
31921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
31931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = map.ticker.read();
31941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        preWriteCleanup(now);
31951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
31961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = this.count - 1;
31971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
31981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
31991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
32001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
32021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
32031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
32041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
32051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> valueReference = e.getValueReference();
32061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V entryValue = valueReference.get();
32071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            RemovalCause cause;
32091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (map.valueEquivalence.equivalent(value, entryValue)) {
32101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              cause = RemovalCause.EXPLICIT;
32111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else if (entryValue == null && valueReference.isActive()) {
32121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              cause = RemovalCause.COLLECTED;
32131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            } else {
32141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // currently loading
32151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return false;
32161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
32171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ++modCount;
32191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ReferenceEntry<K, V> newFirst = removeValueFromChain(
32201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                first, e, entryKey, hash, valueReference, cause);
32211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            newCount = this.count - 1;
32221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            table.set(index, newFirst);
32231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            this.count = newCount; // write-volatile
32241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return (cause == RemovalCause.EXPLICIT);
32251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
32261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
32271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
32291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
32301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
32311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
32321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
32331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
32341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void clear() {
32361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (count != 0) { // read-volatile
32371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lock();
32381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
32391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
32401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (int i = 0; i < table.length(); ++i) {
32411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) {
32421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              // Loading references aren't actually in the map yet.
32431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (e.getValueReference().isActive()) {
32441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                enqueueNotification(e, RemovalCause.EXPLICIT);
32451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
32461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
32471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
32481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (int i = 0; i < table.length(); ++i) {
32491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            table.set(i, null);
32501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
32511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          clearReferenceQueues();
32521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          writeQueue.clear();
32531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          accessQueue.clear();
32541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          readCount.set(0);
32551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ++modCount;
32571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          count = 0; // write-volatile
32581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
32591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          unlock();
32601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          postWriteCleanup();
32611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
32621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
32631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
32641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
32661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
32671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> removeValueFromChain(ReferenceEntry<K, V> first,
32681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> entry, @Nullable K key, int hash, ValueReference<K, V> valueReference,
32691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        RemovalCause cause) {
32701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      enqueueNotification(key, hash, valueReference, cause);
32711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      writeQueue.remove(entry);
32721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      accessQueue.remove(entry);
32731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (valueReference.isLoading()) {
32751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        valueReference.notifyNewValue(null);
32761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return first;
32771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
32781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return removeEntryFromChain(first, entry);
32791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
32801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
32811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
32821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
32831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
32841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> removeEntryFromChain(ReferenceEntry<K, V> first,
32851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> entry) {
32861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int newCount = count;
32871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> newFirst = entry.getNext();
32881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (ReferenceEntry<K, V> e = first; e != entry; e = e.getNext()) {
32891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (isCollected(e)) {
32901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          removeCollectedEntry(e);
32911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          newCount--;
32921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
32931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          newFirst = copyEntry(e, newFirst);
32941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
32951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
32961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.count = newCount;
32971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return newFirst;
32981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
32991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
33011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void removeCollectedEntry(ReferenceEntry<K, V> entry) {
33021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      enqueueNotification(entry, RemovalCause.COLLECTED);
33031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      writeQueue.remove(entry);
33041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      accessQueue.remove(entry);
33051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
33061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
33081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Removes an entry whose key has been garbage collected.
33091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
33101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean reclaimKey(ReferenceEntry<K, V> entry, int hash) {
33111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
33121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
33131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = count - 1;
33141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
33151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
33161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
33171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
33191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e == entry) {
33201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ++modCount;
33211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ReferenceEntry<K, V> newFirst = removeValueFromChain(
33221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                first, e, e.getKey(), hash, e.getValueReference(), RemovalCause.COLLECTED);
33231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            newCount = this.count - 1;
33241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            table.set(index, newFirst);
33251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            this.count = newCount; // write-volatile
33261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return true;
33271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
33281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
33291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
33311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
33321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
33331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
33341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
33351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
33361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
33381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Removes an entry whose value has been garbage collected.
33391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
33401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean reclaimValue(K key, int hash, ValueReference<K, V> valueReference) {
33411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
33421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
33431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int newCount = this.count - 1;
33441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
33451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
33461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
33471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
33491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
33501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
33511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
33521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> v = e.getValueReference();
33531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (v == valueReference) {
33541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ++modCount;
33551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              ReferenceEntry<K, V> newFirst = removeValueFromChain(
33561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  first, e, entryKey, hash, valueReference, RemovalCause.COLLECTED);
33571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              newCount = this.count - 1;
33581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              table.set(index, newFirst);
33591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              this.count = newCount; // write-volatile
33601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return true;
33611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
33621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return false;
33631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
33641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
33651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
33671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
33681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
33691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (!isHeldByCurrentThread()) { // don't cleanup inside of put
33701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          postWriteCleanup();
33711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
33721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
33731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
33741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean removeLoadingValue(K key, int hash, LoadingValueReference<K, V> valueReference) {
33761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lock();
33771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
33781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
33791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int index = hash & (table.length() - 1);
33801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> first = table.get(index);
33811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
33821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
33831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          K entryKey = e.getKey();
33841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (e.getHash() == hash && entryKey != null
33851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              && map.keyEquivalence.equivalent(key, entryKey)) {
33861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            ValueReference<K, V> v = e.getValueReference();
33871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (v == valueReference) {
33881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              if (valueReference.isActive()) {
33891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                e.setValueReference(valueReference.getOldValue());
33901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              } else {
33911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                ReferenceEntry<K, V> newFirst = removeEntryFromChain(first, e);
33921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                table.set(index, newFirst);
33931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
33941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return true;
33951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
33961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return false;
33971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
33981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
33991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
34011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
34021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        unlock();
34031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        postWriteCleanup();
34041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
34051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
34081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean removeEntry(ReferenceEntry<K, V> entry, int hash, RemovalCause cause) {
34091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int newCount = this.count - 1;
34101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
34111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int index = hash & (table.length() - 1);
34121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> first = table.get(index);
34131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
34151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (e == entry) {
34161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ++modCount;
34171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> newFirst = removeValueFromChain(
34181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              first, e, e.getKey(), hash, e.getValueReference(), cause);
34191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          newCount = this.count - 1;
34201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          table.set(index, newFirst);
34211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          this.count = newCount; // write-volatile
34221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return true;
34231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
34241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
34251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
34271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
34301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns true if the entry has been partially collected, meaning that either the key is null,
34311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * or the value is active but null.
34321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
34331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean isCollected(ReferenceEntry<K, V> entry) {
34341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (entry.getKey() == null) {
34351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return true;
34361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
34371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ValueReference<K, V> valueReference = entry.getValueReference();
34381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (valueReference.get() == null) && valueReference.isActive();
34391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
34421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Performs routine cleanup following a read. Normally cleanup happens during writes. If cleanup
34431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * is not observed after a sufficient number of reads, try cleaning up from the read thread.
34441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
34451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void postReadCleanup() {
34461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if ((readCount.incrementAndGet() & DRAIN_THRESHOLD) == 0) {
34471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        cleanUp();
34481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
34491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
34521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Performs routine cleanup prior to executing a write. This should be called every time a
34531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * write thread acquires the segment lock, immediately after acquiring the lock.
34541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     *
34551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * <p>Post-condition: expireEntries has been run.
34561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
34571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @GuardedBy("Segment.this")
34581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void preWriteCleanup(long now) {
34591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      runLockedCleanup(now);
34601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
34631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Performs routine cleanup following a write.
34641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
34651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void postWriteCleanup() {
34661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      runUnlockedCleanup();
34671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void cleanUp() {
34701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long now = map.ticker.read();
34711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      runLockedCleanup(now);
34721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      runUnlockedCleanup();
34731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void runLockedCleanup(long now) {
34761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (tryLock()) {
34771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
34781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          drainReferenceQueues();
34791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          expireEntries(now); // calls drainRecencyQueue
34801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          readCount.set(0);
34811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } finally {
34821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          unlock();
34831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
34841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
34851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    void runUnlockedCleanup() {
34881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // locked cleanup may generate notifications we can send unlocked
34891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!isHeldByCurrentThread()) {
34901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        map.processPendingNotifications();
34911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
34921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
34931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
34951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class LoadingValueReference<K, V> implements ValueReference<K, V> {
34971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    volatile ValueReference<K, V> oldValue;
34981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
34991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(fry): rename get, then extend AbstractFuture instead of containing SettableFuture
35001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final SettableFuture<V> futureValue = SettableFuture.create();
35011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Stopwatch stopwatch = new Stopwatch();
35021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public LoadingValueReference() {
35041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this(LocalCache.<K, V>unset());
35051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public LoadingValueReference(ValueReference<K, V> oldValue) {
35081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.oldValue = oldValue;
35091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isLoading() {
35131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
35141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isActive() {
35181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return oldValue.isActive();
35191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int getWeight() {
35231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return oldValue.getWeight();
35241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean set(@Nullable V newValue) {
35271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return futureValue.set(newValue);
35281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean setException(Throwable t) {
35311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return setException(futureValue, t);
35321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static boolean setException(SettableFuture<?> future, Throwable t) {
35351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
35361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return future.setException(t);
35371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (Error e) {
35381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // the error will already be propagated by the loading thread
35391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
35401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
35411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private ListenableFuture<V> fullyFailedFuture(Throwable t) {
35441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      SettableFuture<V> future = SettableFuture.create();
35451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      setException(future, t);
35461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return future;
35471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void notifyNewValue(@Nullable V newValue) {
35511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (newValue != null) {
35521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // The pending load was clobbered by a manual write.
35531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // Unblock all pending gets, and have them return the new value.
35541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        set(newValue);
35551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
35561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // The pending load was removed. Delay notifications until loading completes.
35571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        oldValue = unset();
35581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
35591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // TODO(fry): could also cancel loading if we had a handle on its future
35611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ListenableFuture<V> loadFuture(K key, CacheLoader<? super K, V> loader) {
35641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      stopwatch.start();
35651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V previousValue = oldValue.get();
35661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
35671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (previousValue == null) {
35681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          V newValue = loader.load(key);
35691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return set(newValue) ? futureValue : Futures.immediateFuture(newValue);
35701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
35711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ListenableFuture<V> newValue = loader.reload(key, previousValue);
35721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // rely on loadAsync to call set in order to avoid adding a second listener here
35731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return newValue != null ? newValue : Futures.<V>immediateFuture(null);
35741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
35751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (Throwable t) {
35761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return setException(t) ? futureValue : fullyFailedFuture(t);
35771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
35781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long elapsedNanos() {
35811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return stopwatch.elapsedTime(NANOSECONDS);
35821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V waitForValue() throws ExecutionException {
35861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return getUninterruptibly(futureValue);
35871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get() {
35911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return oldValue.get();
35921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> getOldValue() {
35951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return oldValue;
35961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
35971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
35981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
35991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> getEntry() {
36001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
36011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
36021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
36041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
36051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this;
36061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
36071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
36081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Queues
36101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
36121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A custom queue for managing eviction order. Note that this is tightly integrated with {@code
36131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * ReferenceEntry}, upon which it relies to perform its linking.
36141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
36151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note that this entire implementation makes the assumption that all elements which are in
36161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the map are also in this queue, and that all elements not in the queue are not in the map.
36171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
36181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The benefits of creating our own queue are that (1) we can replace elements in the middle
36191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the queue as part of copyWriteEntry, and (2) the contains method is highly optimized
36201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * for the current model.
36211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
36221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class WriteQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
36231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
36241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
36261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public long getWriteTime() {
36271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Long.MAX_VALUE;
36281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
36291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
36311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void setWriteTime(long time) {}
36321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> nextWrite = this;
36341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
36361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public ReferenceEntry<K, V> getNextInWriteQueue() {
36371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return nextWrite;
36381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
36391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
36411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void setNextInWriteQueue(ReferenceEntry<K, V> next) {
36421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.nextWrite = next;
36431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
36441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> previousWrite = this;
36461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
36481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public ReferenceEntry<K, V> getPreviousInWriteQueue() {
36491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return previousWrite;
36501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
36511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
36531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void setPreviousInWriteQueue(ReferenceEntry<K, V> previous) {
36541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.previousWrite = previous;
36551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
36561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
36571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // implements Queue
36591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
36611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean offer(ReferenceEntry<K, V> entry) {
36621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // unlink
36631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectWriteOrder(entry.getPreviousInWriteQueue(), entry.getNextInWriteQueue());
36641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // add to tail
36661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectWriteOrder(head.getPreviousInWriteQueue(), entry);
36671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectWriteOrder(entry, head);
36681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
36701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
36711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
36731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> peek() {
36741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> next = head.getNextInWriteQueue();
36751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (next == head) ? null : next;
36761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
36771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
36791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> poll() {
36801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> next = head.getNextInWriteQueue();
36811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (next == head) {
36821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
36831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
36841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      remove(next);
36861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return next;
36871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
36881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
36901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @SuppressWarnings("unchecked")
36911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean remove(Object o) {
36921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = (ReferenceEntry) o;
36931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> previous = e.getPreviousInWriteQueue();
36941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> next = e.getNextInWriteQueue();
36951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectWriteOrder(previous, next);
36961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nullifyWriteOrder(e);
36971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
36981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return next != NullEntry.INSTANCE;
36991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
37001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
37021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @SuppressWarnings("unchecked")
37031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean contains(Object o) {
37041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = (ReferenceEntry) o;
37051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return e.getNextInWriteQueue() != NullEntry.INSTANCE;
37061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
37071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
37091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isEmpty() {
37101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return head.getNextInWriteQueue() == head;
37111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
37121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
37141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int size() {
37151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int size = 0;
37161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (ReferenceEntry<K, V> e = head.getNextInWriteQueue(); e != head;
37171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          e = e.getNextInWriteQueue()) {
37181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        size++;
37191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return size;
37211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
37221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
37241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear() {
37251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = head.getNextInWriteQueue();
37261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (e != head) {
37271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> next = e.getNextInWriteQueue();
37281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        nullifyWriteOrder(e);
37291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        e = next;
37301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      head.setNextInWriteQueue(head);
37331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      head.setPreviousInWriteQueue(head);
37341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
37351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
37371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterator<ReferenceEntry<K, V>> iterator() {
37381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new AbstractLinkedIterator<ReferenceEntry<K, V>>(peek()) {
37391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
37401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        protected ReferenceEntry<K, V> computeNext(ReferenceEntry<K, V> previous) {
37411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> next = previous.getNextInWriteQueue();
37421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (next == head) ? null : next;
37431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
37441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      };
37451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
37461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
37471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
37491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A custom queue for managing access order. Note that this is tightly integrated with
37501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code ReferenceEntry}, upon which it reliese to perform its linking.
37511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
37521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>Note that this entire implementation makes the assumption that all elements which are in
37531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * the map are also in this queue, and that all elements not in the queue are not in the map.
37541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
37551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>The benefits of creating our own queue are that (1) we can replace elements in the middle
37561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of the queue as part of copyWriteEntry, and (2) the contains method is highly optimized
37571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * for the current model.
37581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
37591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class AccessQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
37601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
37611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
37631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public long getAccessTime() {
37641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Long.MAX_VALUE;
37651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
37681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void setAccessTime(long time) {}
37691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> nextAccess = this;
37711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
37731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public ReferenceEntry<K, V> getNextInAccessQueue() {
37741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return nextAccess;
37751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
37781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void setNextInAccessQueue(ReferenceEntry<K, V> next) {
37791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.nextAccess = next;
37801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> previousAccess = this;
37831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
37851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public ReferenceEntry<K, V> getPreviousInAccessQueue() {
37861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return previousAccess;
37871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
37901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      public void setPreviousInAccessQueue(ReferenceEntry<K, V> previous) {
37911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this.previousAccess = previous;
37921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
37931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
37941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // implements Queue
37961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
37971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
37981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean offer(ReferenceEntry<K, V> entry) {
37991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // unlink
38001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectAccessOrder(entry.getPreviousInAccessQueue(), entry.getNextInAccessQueue());
38011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // add to tail
38031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectAccessOrder(head.getPreviousInAccessQueue(), entry);
38041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectAccessOrder(entry, head);
38051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
38071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> peek() {
38111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> next = head.getNextInAccessQueue();
38121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (next == head) ? null : next;
38131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ReferenceEntry<K, V> poll() {
38171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> next = head.getNextInAccessQueue();
38181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (next == head) {
38191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return null;
38201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
38211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      remove(next);
38231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return next;
38241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @SuppressWarnings("unchecked")
38281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean remove(Object o) {
38291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = (ReferenceEntry) o;
38301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> previous = e.getPreviousInAccessQueue();
38311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> next = e.getNextInAccessQueue();
38321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      connectAccessOrder(previous, next);
38331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nullifyAccessOrder(e);
38341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return next != NullEntry.INSTANCE;
38361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @SuppressWarnings("unchecked")
38401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean contains(Object o) {
38411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = (ReferenceEntry) o;
38421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return e.getNextInAccessQueue() != NullEntry.INSTANCE;
38431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isEmpty() {
38471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return head.getNextInAccessQueue() == head;
38481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int size() {
38521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int size = 0;
38531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (ReferenceEntry<K, V> e = head.getNextInAccessQueue(); e != head;
38541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          e = e.getNextInAccessQueue()) {
38551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        size++;
38561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
38571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return size;
38581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear() {
38621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      ReferenceEntry<K, V> e = head.getNextInAccessQueue();
38631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (e != head) {
38641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        ReferenceEntry<K, V> next = e.getNextInAccessQueue();
38651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        nullifyAccessOrder(e);
38661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        e = next;
38671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
38681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      head.setNextInAccessQueue(head);
38701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      head.setPreviousInAccessQueue(head);
38711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
38741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterator<ReferenceEntry<K, V>> iterator() {
38751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new AbstractLinkedIterator<ReferenceEntry<K, V>>(peek()) {
38761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
38771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        protected ReferenceEntry<K, V> computeNext(ReferenceEntry<K, V> previous) {
38781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ReferenceEntry<K, V> next = previous.getNextInAccessQueue();
38791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (next == head) ? null : next;
38801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
38811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      };
38821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
38841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Cache support
38861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void cleanUp() {
38881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Segment<?, ?> segment : segments) {
38891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      segment.cleanUp();
38901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
38911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
38921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // ConcurrentMap methods
38941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
38951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
38961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean isEmpty() {
38971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
38981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Sum per-segment modCounts to avoid mis-reporting when elements are concurrently added and
38991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * removed in one segment while checking another, in which case the table was never actually
39001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * empty at any point. (The sum ensures accuracy up through at least 1<<31 per-segment
39011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * modifications before recheck.)  Method containsValue() uses similar constructions for
39021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * stability checks.
39031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
39041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long sum = 0L;
39051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Segment<K, V>[] segments = this.segments;
39061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < segments.length; ++i) {
39071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (segments[i].count != 0) {
39081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
39091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
39101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sum += segments[i].modCount;
39111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
39121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (sum != 0L) { // recheck unless no modifications
39141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (int i = 0; i < segments.length; ++i) {
39151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (segments[i].count != 0) {
39161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return false;
39171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
39181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        sum -= segments[i].modCount;
39191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
39201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (sum != 0L) {
39211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
39221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
39231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
39241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return true;
39251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  long longSize() {
39281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Segment<K, V>[] segments = this.segments;
39291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long sum = 0;
39301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < segments.length; ++i) {
39311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sum += segments[i].count;
39321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
39331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return sum;
39341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
39371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int size() {
39381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Ints.saturatedCast(longSize());
39391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
39421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
39431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public V get(@Nullable Object key) {
39441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (key == null) {
39451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
39461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
39471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
39481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).get(key, hash);
39491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
39521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public V getIfPresent(Object key) {
39531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(checkNotNull(key));
39541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V value = segmentFor(hash).get(key, hash);
39551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (value == null) {
39561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      globalStatsCounter.recordMisses(1);
39571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
39581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      globalStatsCounter.recordHits(1);
39591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
39601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return value;
39611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  V get(K key, CacheLoader<? super K, V> loader) throws ExecutionException {
39641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(checkNotNull(key));
39651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).get(key, hash, loader);
39661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  V getOrLoad(K key) throws ExecutionException {
39691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return get(key, defaultLoader);
39701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys) {
39731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hits = 0;
39741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int misses = 0;
39751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Map<K, V> result = Maps.newLinkedHashMap();
39771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (K key : keys) {
39781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value = get(key);
39791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (value == null) {
39801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        misses++;
39811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
39821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        result.put(key, value);
39831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        hits++;
39841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
39851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
39861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    globalStatsCounter.recordHits(hits);
39871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    globalStatsCounter.recordMisses(misses);
39881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return ImmutableMap.copyOf(result);
39891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
39901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ImmutableMap<K, V> getAll(Iterable<? extends K> keys)
39921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws ExecutionException {
39931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hits = 0;
39941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int misses = 0;
39951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
39961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Map<K, V> result = Maps.newLinkedHashMap();
39971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<K> keysToLoad = Sets.newLinkedHashSet();
39981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (K key : keys) {
39991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value = get(key);
40001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!result.containsKey(key)) {
40011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        result.put(key, value);
40021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value == null) {
40031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          misses++;
40041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          keysToLoad.add(key);
40051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
40061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          hits++;
40071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
40081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
40091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
40101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
40121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!keysToLoad.isEmpty()) {
40131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        try {
40141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          Map<K, V> newEntries = loadAll(keysToLoad, defaultLoader);
40151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (K key : keysToLoad) {
40161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V value = newEntries.get(key);
40171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (value == null) {
40181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              throw new InvalidCacheLoadException("loadAll failed to return a value for " + key);
40191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
40201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            result.put(key, value);
40211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
40221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } catch (UnsupportedLoadingOperationException e) {
40231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // loadAll not implemented, fallback to load
40241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (K key : keysToLoad) {
40251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            misses--; // get will count this miss
40261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            result.put(key, get(key, defaultLoader));
40271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
40281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
40291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
40301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ImmutableMap.copyOf(result);
40311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
40321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      globalStatsCounter.recordHits(hits);
40331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      globalStatsCounter.recordMisses(misses);
40341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
40351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
40361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
40381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the result of calling {@link CacheLoader#loadAll}, or null if {@code loader} doesn't
40391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * implement {@code loadAll}.
40401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
40411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
40421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Map<K, V> loadAll(Set<? extends K> keys, CacheLoader<? super K, V> loader)
40431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throws ExecutionException {
40441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Stopwatch stopwatch = new Stopwatch().start();
40451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Map<K, V> result;
40461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean success = false;
40471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
40481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @SuppressWarnings("unchecked") // safe since all keys extend K
40491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Map<K, V> map = (Map<K, V>) loader.loadAll(keys);
40501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      result = map;
40511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      success = true;
40521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (UnsupportedLoadingOperationException e) {
40531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      success = true;
40541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw e;
40551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (RuntimeException e) {
40561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UncheckedExecutionException(e);
40571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (Exception e) {
40581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new ExecutionException(e);
40591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (Error e) {
40601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new ExecutionError(e);
40611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
40621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!success) {
40631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        globalStatsCounter.recordLoadException(stopwatch.elapsedTime(NANOSECONDS));
40641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
40651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
40661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (result == null) {
40681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      globalStatsCounter.recordLoadException(stopwatch.elapsedTime(NANOSECONDS));
40691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new InvalidCacheLoadException(loader + " returned null map from loadAll");
40701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
40711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    stopwatch.stop();
40731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(fry): batch by segment
40741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean nullsPresent = false;
40751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Map.Entry<K, V> entry : result.entrySet()) {
40761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      K key = entry.getKey();
40771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V value = entry.getValue();
40781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (key == null || value == null) {
40791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // delay failure until non-null entries are stored
40801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        nullsPresent = true;
40811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
40821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        put(key, value);
40831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
40841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
40851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (nullsPresent) {
40871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      globalStatsCounter.recordLoadException(stopwatch.elapsedTime(NANOSECONDS));
40881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new InvalidCacheLoadException(loader + " returned null keys or values from loadAll");
40891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
40901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(fry): record count of loaded entries
40921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    globalStatsCounter.recordLoadSuccess(stopwatch.elapsedTime(NANOSECONDS));
40931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
40941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
40951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
40961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
40971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the internal entry for the specified key. The entry may be loading, expired, or
40981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * partially collected.
40991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
41001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ReferenceEntry<K, V> getEntry(@Nullable Object key) {
41011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
41021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (key == null) {
41031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
41041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
41051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
41061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).getEntry(key, hash);
41071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
41101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the live internal entry for the specified key.
41111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
41121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  ReferenceEntry<K, V> getLiveEntry(@Nullable Object key) {
41131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
41141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (key == null) {
41151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
41161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
41171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
41181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).getLiveEntry(key, hash, ticker.read());
41191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  void refresh(K key) {
41221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(checkNotNull(key));
41231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    segmentFor(hash).refresh(key, hash, defaultLoader);
41241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
41271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean containsKey(@Nullable Object key) {
41281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
41291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (key == null) {
41301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
41311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
41321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
41331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).containsKey(key, hash);
41341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
41371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean containsValue(@Nullable Object value) {
41381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
41391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (value == null) {
41401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
41411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
41421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // This implementation is patterned after ConcurrentHashMap, but without the locking. The only
41441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // way for it to return a false negative would be for the target value to jump around in the map
41451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // such that none of the subsequent iterations observed it, despite the fact that at every point
41461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // in time it was present somewhere int the map. This becomes increasingly unlikely as
41471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // CONTAINS_VALUE_RETRIES increases, though without locking it is theoretically possible.
41481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long now = ticker.read();
41491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Segment<K,V>[] segments = this.segments;
41501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long last = -1L;
41511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) {
41521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      long sum = 0L;
41531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (Segment<K, V> segment : segments) {
41541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // ensure visibility of most recent completed write
41551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @SuppressWarnings({"UnusedDeclaration", "unused"})
41561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int c = segment.count; // read-volatile
41571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
41591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (int j = 0 ; j < table.length(); j++) {
41601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          for (ReferenceEntry<K, V> e = table.get(j); e != null; e = e.getNext()) {
41611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            V v = segment.getLiveValue(e, now);
41621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (v != null && valueEquivalence.equivalent(value, v)) {
41631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return true;
41641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
41651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
41661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
41671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        sum += segment.modCount;
41681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
41691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (sum == last) {
41701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        break;
41711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
41721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      last = sum;
41731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
41741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
41751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
41781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public V put(K key, V value) {
41791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(key);
41801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(value);
41811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
41821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).put(key, hash, value, false);
41831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
41861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public V putIfAbsent(K key, V value) {
41871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(key);
41881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(value);
41891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
41901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).put(key, hash, value, true);
41911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
41931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
41941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void putAll(Map<? extends K, ? extends V> m) {
41951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Entry<? extends K, ? extends V> e : m.entrySet()) {
41961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      put(e.getKey(), e.getValue());
41971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
41981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
41991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public V remove(@Nullable Object key) {
42021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (key == null) {
42031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return null;
42041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
42051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
42061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).remove(key, hash);
42071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean remove(@Nullable Object key, @Nullable Object value) {
42111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (key == null || value == null) {
42121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
42131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
42141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
42151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).remove(key, hash, value);
42161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean replace(K key, @Nullable V oldValue, V newValue) {
42201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(key);
42211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(newValue);
42221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (oldValue == null) {
42231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
42241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
42251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
42261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).replace(key, hash, oldValue, newValue);
42271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public V replace(K key, V value) {
42311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(key);
42321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(value);
42331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int hash = hash(key);
42341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return segmentFor(hash).replace(key, hash, value);
42351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void clear() {
42391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Segment<K, V> segment : segments) {
42401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      segment.clear();
42411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
42421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  void invalidateAll(Iterable<?> keys) {
42451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO(fry): batch by segment
42461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Object key : keys) {
42471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      remove(key);
42481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
42491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Set<K> keySet;
42521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Set<K> keySet() {
42551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
42561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<K> ks = keySet;
42571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (ks != null) ? ks : (keySet = new KeySet());
42581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Collection<V> values;
42611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Collection<V> values() {
42641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
42651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<V> vs = values;
42661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (vs != null) ? vs : (values = new Values());
42671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Set<Entry<K, V>> entrySet;
42701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
42721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public Set<Entry<K, V>> entrySet() {
42731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // does not impact recency ordering
42741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<Entry<K, V>> es = entrySet;
42751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (es != null) ? es : (entrySet = new EntrySet());
42761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
42771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Iterator Support
42791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract class HashIterator {
42811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int nextSegmentIndex;
42831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int nextTableIndex;
42841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Segment<K, V> currentSegment;
42851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AtomicReferenceArray<ReferenceEntry<K, V>> currentTable;
42861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ReferenceEntry<K, V> nextEntry;
42871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WriteThroughEntry nextExternal;
42881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WriteThroughEntry lastReturned;
42891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    HashIterator() {
42911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nextSegmentIndex = segments.length - 1;
42921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nextTableIndex = -1;
42931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      advance();
42941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
42951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final void advance() {
42971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      nextExternal = null;
42981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
42991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (nextInChain()) {
43001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return;
43011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (nextInTable()) {
43041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return;
43051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (nextSegmentIndex >= 0) {
43081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        currentSegment = segments[nextSegmentIndex--];
43091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (currentSegment.count != 0) {
43101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          currentTable = currentSegment.table;
43111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          nextTableIndex = currentTable.length() - 1;
43121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (nextInTable()) {
43131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return;
43141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
43151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
43161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
43201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Finds the next entry in the current chain. Returns true if an entry was found.
43211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
43221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean nextInChain() {
43231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (nextEntry != null) {
43241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (nextEntry = nextEntry.getNext(); nextEntry != null; nextEntry = nextEntry.getNext()) {
43251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (advanceTo(nextEntry)) {
43261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return true;
43271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
43281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
43291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
43311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
43341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Finds the next entry in the current table. Returns true if an entry was found.
43351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
43361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean nextInTable() {
43371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (nextTableIndex >= 0) {
43381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if ((nextEntry = currentTable.get(nextTableIndex--)) != null) {
43391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          if (advanceTo(nextEntry) || nextInChain()) {
43401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return true;
43411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
43421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
43431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
43451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
43481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Advances to the given entry. Returns true if the entry was valid, false if it should be
43491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * skipped.
43501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
43511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean advanceTo(ReferenceEntry<K, V> entry) {
43521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
43531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long now = ticker.read();
43541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        K key = entry.getKey();
43551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        V value = getLiveValue(entry, now);
43561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (value != null) {
43571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          nextExternal = new WriteThroughEntry(key, value);
43581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return true;
43591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        } else {
43601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          // Skip stale entry.
43611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return false;
43621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
43631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } finally {
43641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        currentSegment.postReadCleanup();
43651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean hasNext() {
43691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextExternal != null;
43701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WriteThroughEntry nextEntry() {
43731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (nextExternal == null) {
43741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new NoSuchElementException();
43751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
43761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lastReturned = nextExternal;
43771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      advance();
43781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return lastReturned;
43791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void remove() {
43821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkState(lastReturned != null);
43831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      LocalCache.this.remove(lastReturned.getKey());
43841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lastReturned = null;
43851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
43871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class KeyIterator extends HashIterator implements Iterator<K> {
43891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
43911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public K next() {
43921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextEntry().getKey();
43931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
43941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
43951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class ValueIterator extends HashIterator implements Iterator<V> {
43971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
43981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
43991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V next() {
44001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextEntry().getValue();
44011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
44031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
44051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Custom Entry class used by EntryIterator.next(), that relays setValue changes to the
44061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * underlying map.
44071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
44081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class WriteThroughEntry implements Entry<K, V> {
44091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final K key; // non-null
44101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    V value; // non-null
44111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    WriteThroughEntry(K key, V value) {
44131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.key = key;
44141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.value = value;
44151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public K getKey() {
44191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return key;
44201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V getValue() {
44241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return value;
44251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean equals(@Nullable Object object) {
44291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Cannot use key and value equivalence
44301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (object instanceof Entry) {
44311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Entry<?, ?> that = (Entry<?, ?>) object;
44321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return key.equals(that.getKey()) && value.equals(that.getValue());
44331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
44341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
44351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int hashCode() {
44391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // Cannot use key and value equivalence
44401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return key.hashCode() ^ value.hashCode();
44411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V setValue(V newValue) {
44451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new UnsupportedOperationException();
44461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /**
44491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * Returns a string representation of the form <code>{key}={value}</code>.
44501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
44511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public String toString() {
44521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return getKey() + "=" + getValue();
44531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
44551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class EntryIterator extends HashIterator implements Iterator<Entry<K, V>> {
44571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Entry<K, V> next() {
44601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return nextEntry();
44611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
44631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class KeySet extends AbstractSet<K> {
44651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterator<K> iterator() {
44681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new KeyIterator();
44691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int size() {
44731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.size();
44741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isEmpty() {
44781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.isEmpty();
44791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean contains(Object o) {
44831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.containsKey(o);
44841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean remove(Object o) {
44881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.remove(o) != null;
44891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
44921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear() {
44931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      LocalCache.this.clear();
44941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
44951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
44961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class Values extends AbstractCollection<V> {
44981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
44991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterator<V> iterator() {
45011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new ValueIterator();
45021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int size() {
45061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.size();
45071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isEmpty() {
45111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.isEmpty();
45121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean contains(Object o) {
45161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.containsValue(o);
45171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear() {
45211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      LocalCache.this.clear();
45221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
45241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final class EntrySet extends AbstractSet<Entry<K, V>> {
45261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public Iterator<Entry<K, V>> iterator() {
45291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new EntryIterator();
45301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean contains(Object o) {
45341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!(o instanceof Entry)) {
45351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
45361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
45371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Entry<?, ?> e = (Entry<?, ?>) o;
45381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Object key = e.getKey();
45391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (key == null) {
45401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
45411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
45421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      V v = LocalCache.this.get(key);
45431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return v != null && valueEquivalence.equivalent(e.getValue(), v);
45451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean remove(Object o) {
45491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (!(o instanceof Entry)) {
45501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return false;
45511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
45521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Entry<?, ?> e = (Entry<?, ?>) o;
45531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Object key = e.getKey();
45541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return key != null && LocalCache.this.remove(key, e.getValue());
45551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public int size() {
45591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.size();
45601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public boolean isEmpty() {
45641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return LocalCache.this.isEmpty();
45651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
45681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void clear() {
45691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      LocalCache.this.clear();
45701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
45711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
45721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // Serialization Support
45741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
45761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Serializes the configuration of a LocalCache, reconsitituting it as a Cache using
45771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * CacheBuilder upon deserialization. An instance of this class is fit for use by the writeReplace
45781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of LocalManualCache.
45791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
45801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Unfortunately, readResolve() doesn't get called when a circular dependency is present, so the
45811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * proxy must be able to behave as the cache itself.
45821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
45831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class ManualSerializationProxy<K, V>
45841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ForwardingCache<K, V> implements Serializable {
45851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 1;
45861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
45871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Strength keyStrength;
45881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Strength valueStrength;
45891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Equivalence<Object> keyEquivalence;
45901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Equivalence<Object> valueEquivalence;
45911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final long expireAfterWriteNanos;
45921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final long expireAfterAccessNanos;
45931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final long maxWeight;
45941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Weigher<K, V> weigher;
45951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final int concurrencyLevel;
45961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final RemovalListener<? super K, ? super V> removalListener;
45971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Ticker ticker;
45981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final CacheLoader<? super K, V> loader;
45991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    transient Cache<K, V> delegate;
46011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ManualSerializationProxy(LocalCache<K, V> cache) {
46031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this(
46041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.keyStrength,
46051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.valueStrength,
46061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.keyEquivalence,
46071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.valueEquivalence,
46081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.expireAfterWriteNanos,
46091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.expireAfterAccessNanos,
46101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.maxWeight,
46111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.weigher,
46121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.concurrencyLevel,
46131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.removalListener,
46141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.ticker,
46151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          cache.defaultLoader);
46161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
46171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private ManualSerializationProxy(
46191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Strength keyStrength, Strength valueStrength,
46201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
46211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        long expireAfterWriteNanos, long expireAfterAccessNanos, long maxWeight,
46221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Weigher<K, V> weigher, int concurrencyLevel,
46231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        RemovalListener<? super K, ? super V> removalListener,
46241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        Ticker ticker, CacheLoader<? super K, V> loader) {
46251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.keyStrength = keyStrength;
46261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.valueStrength = valueStrength;
46271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.keyEquivalence = keyEquivalence;
46281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.valueEquivalence = valueEquivalence;
46291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.expireAfterWriteNanos = expireAfterWriteNanos;
46301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.expireAfterAccessNanos = expireAfterAccessNanos;
46311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.maxWeight = maxWeight;
46321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.weigher = weigher;
46331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.concurrencyLevel = concurrencyLevel;
46341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.removalListener = removalListener;
46351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.ticker = (ticker == Ticker.systemTicker() || ticker == NULL_TICKER)
46361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          ? null : ticker;
46371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.loader = loader;
46381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
46391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   CacheBuilder<Object, Object> recreateCacheBuilder() {
46411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder()
46421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .setKeyStrength(keyStrength)
46431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .setValueStrength(valueStrength)
46441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .keyEquivalence(keyEquivalence)
46451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .valueEquivalence(valueEquivalence)
46461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .concurrencyLevel(concurrencyLevel);
46471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.strictParsing = false;
46481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.removalListener(removalListener);
46491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (expireAfterWriteNanos > 0) {
46501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS);
46511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
46521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (expireAfterAccessNanos > 0) {
46531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.expireAfterAccess(expireAfterAccessNanos, TimeUnit.NANOSECONDS);
46541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
46551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (weigher != OneWeigher.INSTANCE) {
46561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.weigher(weigher);
46571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (maxWeight != UNSET_INT) {
46581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          builder.maximumWeight(maxWeight);
46591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
46601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } else {
46611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (maxWeight != UNSET_INT) {
46621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          builder.maximumSize(maxWeight);
46631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
46641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
46651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (ticker != null) {
46661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.ticker(ticker);
46671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
46681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return builder;
46691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
46701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
46721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      in.defaultReadObject();
46731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      CacheBuilder<Object, Object> builder = recreateCacheBuilder();
46741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.delegate = builder.build();
46751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
46761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private Object readResolve() {
46781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
46791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
46801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
46821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    protected Cache<K, V> delegate() {
46831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return delegate;
46841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
46851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
46861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
46881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Serializes the configuration of a LocalCache, reconsitituting it as an LoadingCache using
46891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * CacheBuilder upon deserialization. An instance of this class is fit for use by the writeReplace
46901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * of LocalLoadingCache.
46911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
46921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Unfortunately, readResolve() doesn't get called when a circular dependency is present, so the
46931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * proxy must be able to behave as the cache itself.
46941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
46951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static final class LoadingSerializationProxy<K, V>
46961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends ManualSerializationProxy<K, V> implements LoadingCache<K, V>, Serializable {
46971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 1;
46981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
46991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    transient LoadingCache<K, V> autoDelegate;
47001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LoadingSerializationProxy(LocalCache<K, V> cache) {
47021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(cache);
47031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
47061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      in.defaultReadObject();
47071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      CacheBuilder<Object, Object> builder = recreateCacheBuilder();
47081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.autoDelegate = builder.build(loader);
47091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get(K key) throws ExecutionException {
47131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return autoDelegate.get(key);
47141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V getUnchecked(K key) {
47181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return autoDelegate.getUnchecked(key);
47191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
47231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return autoDelegate.getAll(keys);
47241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public final V apply(K key) {
47281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return autoDelegate.apply(key);
47291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void refresh(K key) {
47331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      autoDelegate.refresh(key);
47341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private Object readResolve() {
47371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return autoDelegate;
47381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
47401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class LocalManualCache<K, V> implements Cache<K, V>, Serializable {
47421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final LocalCache<K, V> localCache;
47431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LocalManualCache(CacheBuilder<? super K, ? super V> builder) {
47451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this(builder, null);
47461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    protected LocalManualCache(CacheBuilder<? super K, ? super V> builder,
47491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        CacheLoader<? super K, V> loader) {
47501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.localCache = new LocalCache<K, V>(builder, loader);
47511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Cache methods
47541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
47571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V getIfPresent(K key) {
47581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache.getIfPresent(key);
47591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get(K key, final Callable<? extends V> valueLoader) throws ExecutionException {
47631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(valueLoader);
47641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache.get(key, new CacheLoader<Object, V>() {
47651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        @Override
47661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        public V load(Object key) throws Exception {
47671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return valueLoader.call();
47681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
47691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      });
47701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ImmutableMap<K, V> getAllPresent(Iterable<? extends K> keys) {
47741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache.getAllPresent(keys);
47751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void put(K key, V value) {
47791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      localCache.put(key, value);
47801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void invalidate(Object key) {
47841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkNotNull(key);
47851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      localCache.remove(key);
47861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void invalidateAll(Iterable<?> keys) {
47901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      localCache.invalidateAll(keys);
47911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void invalidateAll() {
47951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      localCache.clear();
47961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
47971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
47981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
47991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public long size() {
48001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache.longSize();
48011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
48041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ConcurrentMap<K, V> asMap() {
48051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache;
48061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
48091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public CacheStats stats() {
48101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      SimpleStatsCounter aggregator = new SimpleStatsCounter();
48111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      aggregator.incrementBy(localCache.globalStatsCounter);
48121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      for (Segment<K, V> segment : localCache.segments) {
48131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        aggregator.incrementBy(segment.statsCounter);
48141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
48151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return aggregator.snapshot();
48161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
48191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void cleanUp() {
48201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      localCache.cleanUp();
48211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /*
48241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * These methods have been moved to LoadingCache, but they temporarily
48251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     * remain in Cache in Guava.
48261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert     */
48271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V get(K key) throws ExecutionException {
48291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache.getOrLoad(key);
48301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public V getUnchecked(K key) {
48331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
48341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return get(key);
48351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (ExecutionException e) {
48361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new UncheckedExecutionException(e.getCause());
48371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
48381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public final V apply(K key) {
48411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return getUnchecked(key);
48421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Serialization Support
48451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 1;
48471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Object writeReplace() {
48491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new ManualSerializationProxy<K, V>(localCache);
48501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
48521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class LocalLoadingCache<K, V>
48541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends LocalManualCache<K, V> implements LoadingCache<K, V> {
48551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    LocalLoadingCache(CacheBuilder<? super K, ? super V> builder,
48571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        CacheLoader<? super K, V> loader) {
48581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(builder, checkNotNull(loader));
48591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Cache methods
48621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
48641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public ImmutableMap<K, V> getAll(Iterable<? extends K> keys) throws ExecutionException {
48651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return localCache.getAll(keys);
48661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override
48691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public void refresh(K key) {
48701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      localCache.refresh(key);
48711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // Serialization Support
48741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 1;
48761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
48771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Object writeReplace() {
48781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new LoadingSerializationProxy<K, V>(localCache);
48791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
48801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
48811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
4882