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