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