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