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