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