1/*
2 * Copyright (C) 2009 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the License
10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11 * or implied. See the License for the specific language governing permissions and limitations under
12 * the License.
13 */
14
15package com.google.common.collect;
16
17import static com.google.common.base.Preconditions.checkNotNull;
18import static com.google.common.base.Preconditions.checkState;
19
20import com.google.common.annotations.VisibleForTesting;
21import com.google.common.base.Equivalence;
22import com.google.common.base.Equivalences;
23import com.google.common.base.Ticker;
24import com.google.common.collect.GenericMapMaker.NullListener;
25import com.google.common.collect.MapMaker.RemovalCause;
26import com.google.common.collect.MapMaker.RemovalListener;
27import com.google.common.collect.MapMaker.RemovalNotification;
28import com.google.common.primitives.Ints;
29
30import java.io.IOException;
31import java.io.ObjectInputStream;
32import java.io.ObjectOutputStream;
33import java.io.Serializable;
34import java.lang.ref.Reference;
35import java.lang.ref.ReferenceQueue;
36import java.lang.ref.SoftReference;
37import java.lang.ref.WeakReference;
38import java.util.AbstractCollection;
39import java.util.AbstractMap;
40import java.util.AbstractQueue;
41import java.util.AbstractSet;
42import java.util.Collection;
43import java.util.Iterator;
44import java.util.Map;
45import java.util.NoSuchElementException;
46import java.util.Queue;
47import java.util.Set;
48import java.util.concurrent.CancellationException;
49import java.util.concurrent.ConcurrentLinkedQueue;
50import java.util.concurrent.ConcurrentMap;
51import java.util.concurrent.ExecutionException;
52import java.util.concurrent.TimeUnit;
53import java.util.concurrent.atomic.AtomicInteger;
54import java.util.concurrent.atomic.AtomicReferenceArray;
55import java.util.concurrent.locks.ReentrantLock;
56import java.util.logging.Level;
57import java.util.logging.Logger;
58
59import javax.annotation.Nullable;
60import javax.annotation.concurrent.GuardedBy;
61
62/**
63 * The concurrent hash map implementation built by {@link MapMaker}.
64 *
65 * <p>This implementation is heavily derived from revision 1.96 of <a
66 * href="http://tinyurl.com/ConcurrentHashMap">ConcurrentHashMap.java</a>.
67 *
68 * @author Bob Lee
69 * @author Charles Fry
70 * @author Doug Lea ({@code ConcurrentHashMap})
71 */
72class MapMakerInternalMap<K, V>
73    extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable {
74
75  /*
76   * The basic strategy is to subdivide the table among Segments, each of which itself is a
77   * concurrently readable hash table. The map supports non-blocking reads and concurrent writes
78   * across different segments.
79   *
80   * If a maximum size is specified, a best-effort bounding is performed per segment, using a
81   * page-replacement algorithm to determine which entries to evict when the capacity has been
82   * exceeded.
83   *
84   * The page replacement algorithm's data structures are kept casually consistent with the map. The
85   * ordering of writes to a segment is sequentially consistent. An update to the map and recording
86   * of reads may not be immediately reflected on the algorithm's data structures. These structures
87   * are guarded by a lock and operations are applied in batches to avoid lock contention. The
88   * penalty of applying the batches is spread across threads so that the amortized cost is slightly
89   * higher than performing just the operation without enforcing the capacity constraint.
90   *
91   * This implementation uses a per-segment queue to record a memento of the additions, removals,
92   * and accesses that were performed on the map. The queue is drained on writes and when it exceeds
93   * its capacity threshold.
94   *
95   * The Least Recently Used page replacement algorithm was chosen due to its simplicity, high hit
96   * rate, and ability to be implemented with O(1) time complexity. The initial LRU implementation
97   * operates per-segment rather than globally for increased implementation simplicity. We expect
98   * the cache hit rate to be similar to that of a global LRU algorithm.
99   */
100
101  // Constants
102
103  /**
104   * The maximum capacity, used if a higher value is implicitly specified by either of the
105   * constructors with arguments. MUST be a power of two <= 1<<30 to ensure that entries are
106   * indexable using ints.
107   */
108  static final int MAXIMUM_CAPACITY = Ints.MAX_POWER_OF_TWO;
109
110  /** The maximum number of segments to allow; used to bound constructor arguments. */
111  static final int MAX_SEGMENTS = 1 << 16; // slightly conservative
112
113  /** Number of (unsynchronized) retries in the containsValue method. */
114  static final int CONTAINS_VALUE_RETRIES = 3;
115
116  /**
117   * Number of cache access operations that can be buffered per segment before the cache's recency
118   * ordering information is updated. This is used to avoid lock contention by recording a memento
119   * of reads and delaying a lock acquisition until the threshold is crossed or a mutation occurs.
120   *
121   * <p>This must be a (2^n)-1 as it is used as a mask.
122   */
123  static final int DRAIN_THRESHOLD = 0x3F;
124
125  /**
126   * Maximum number of entries to be drained in a single cleanup run. This applies independently to
127   * the cleanup queue and both reference queues.
128   */
129  // TODO(fry): empirically optimize this
130  static final int DRAIN_MAX = 16;
131
132  static final long CLEANUP_EXECUTOR_DELAY_SECS = 60;
133
134  // Fields
135
136  private static final Logger logger = Logger.getLogger(MapMakerInternalMap.class.getName());
137
138  /**
139   * Mask value for indexing into segments. The upper bits of a key's hash code are used to choose
140   * the segment.
141   */
142  final transient int segmentMask;
143
144  /**
145   * Shift value for indexing within segments. Helps prevent entries that end up in the same segment
146   * from also ending up in the same bucket.
147   */
148  final transient int segmentShift;
149
150  /** The segments, each of which is a specialized hash table. */
151  final transient Segment<K, V>[] segments;
152
153  /** The concurrency level. */
154  final int concurrencyLevel;
155
156  /** Strategy for comparing keys. */
157  final Equivalence<Object> keyEquivalence;
158
159  /** Strategy for comparing values. */
160  final Equivalence<Object> valueEquivalence;
161
162  /** Strategy for referencing keys. */
163  final Strength keyStrength;
164
165  /** Strategy for referencing values. */
166  final Strength valueStrength;
167
168  /** The maximum size of this map. MapMaker.UNSET_INT if there is no maximum. */
169  final int maximumSize;
170
171  /** How long after the last access to an entry the map will retain that entry. */
172  final long expireAfterAccessNanos;
173
174  /** How long after the last write to an entry the map will retain that entry. */
175  final long expireAfterWriteNanos;
176
177  /** Entries waiting to be consumed by the removal listener. */
178  // TODO(fry): define a new type which creates event objects and automates the clear logic
179  final Queue<RemovalNotification<K, V>> removalNotificationQueue;
180
181  /**
182   * A listener that is invoked when an entry is removed due to expiration or garbage collection of
183   * soft/weak entries.
184   */
185  final RemovalListener<K, V> removalListener;
186
187  /** Factory used to create new entries. */
188  final transient EntryFactory entryFactory;
189
190  /** Measures time in a testable way. */
191  final Ticker ticker;
192
193  /**
194   * Creates a new, empty map with the specified strategy, initial capacity and concurrency level.
195   */
196  MapMakerInternalMap(MapMaker builder) {
197    concurrencyLevel = Math.min(builder.getConcurrencyLevel(), MAX_SEGMENTS);
198
199    keyStrength = builder.getKeyStrength();
200    valueStrength = builder.getValueStrength();
201
202    keyEquivalence = builder.getKeyEquivalence();
203    valueEquivalence = builder.getValueEquivalence();
204
205    maximumSize = builder.maximumSize;
206    expireAfterAccessNanos = builder.getExpireAfterAccessNanos();
207    expireAfterWriteNanos = builder.getExpireAfterWriteNanos();
208
209    entryFactory = EntryFactory.getFactory(keyStrength, expires(), evictsBySize());
210    ticker = builder.getTicker();
211
212    removalListener = builder.getRemovalListener();
213    removalNotificationQueue = (removalListener == NullListener.INSTANCE)
214        ? MapMakerInternalMap.<RemovalNotification<K, V>>discardingQueue()
215        : new ConcurrentLinkedQueue<RemovalNotification<K, V>>();
216
217    int initialCapacity = Math.min(builder.getInitialCapacity(), MAXIMUM_CAPACITY);
218    if (evictsBySize()) {
219      initialCapacity = Math.min(initialCapacity, maximumSize);
220    }
221
222    // Find power-of-two sizes best matching arguments. Constraints:
223    // (segmentCount <= maximumSize)
224    // && (concurrencyLevel > maximumSize || segmentCount > concurrencyLevel)
225    int segmentShift = 0;
226    int segmentCount = 1;
227    while (segmentCount < concurrencyLevel
228        && (!evictsBySize() || segmentCount * 2 <= maximumSize)) {
229      ++segmentShift;
230      segmentCount <<= 1;
231    }
232    this.segmentShift = 32 - segmentShift;
233    segmentMask = segmentCount - 1;
234
235    this.segments = newSegmentArray(segmentCount);
236
237    int segmentCapacity = initialCapacity / segmentCount;
238    if (segmentCapacity * segmentCount < initialCapacity) {
239      ++segmentCapacity;
240    }
241
242    int segmentSize = 1;
243    while (segmentSize < segmentCapacity) {
244      segmentSize <<= 1;
245    }
246
247    if (evictsBySize()) {
248      // Ensure sum of segment max sizes = overall max size
249      int maximumSegmentSize = maximumSize / segmentCount + 1;
250      int remainder = maximumSize % segmentCount;
251      for (int i = 0; i < this.segments.length; ++i) {
252        if (i == remainder) {
253          maximumSegmentSize--;
254        }
255        this.segments[i] =
256            createSegment(segmentSize, maximumSegmentSize);
257      }
258    } else {
259      for (int i = 0; i < this.segments.length; ++i) {
260        this.segments[i] =
261            createSegment(segmentSize, MapMaker.UNSET_INT);
262      }
263    }
264  }
265
266  boolean evictsBySize() {
267    return maximumSize != MapMaker.UNSET_INT;
268  }
269
270  boolean expires() {
271    return expiresAfterWrite() || expiresAfterAccess();
272  }
273
274  boolean expiresAfterWrite() {
275    return expireAfterWriteNanos > 0;
276  }
277
278  boolean expiresAfterAccess() {
279    return expireAfterAccessNanos > 0;
280  }
281
282  boolean usesKeyReferences() {
283    return keyStrength != Strength.STRONG;
284  }
285
286  boolean usesValueReferences() {
287    return valueStrength != Strength.STRONG;
288  }
289
290  enum Strength {
291    /*
292     * TODO(kevinb): If we strongly reference the value and aren't computing, we needn't wrap the
293     * value. This could save ~8 bytes per entry.
294     */
295
296    STRONG {
297      @Override
298      <K, V> ValueReference<K, V> referenceValue(
299          Segment<K, V> segment, ReferenceEntry<K, V> entry, V value) {
300        return new StrongValueReference<K, V>(value);
301      }
302
303      @Override
304      Equivalence<Object> defaultEquivalence() {
305        return Equivalences.equals();
306      }
307    },
308
309    SOFT {
310      @Override
311      <K, V> ValueReference<K, V> referenceValue(
312          Segment<K, V> segment, ReferenceEntry<K, V> entry, V value) {
313        return new SoftValueReference<K, V>(segment.valueReferenceQueue, value, entry);
314      }
315
316      @Override
317      Equivalence<Object> defaultEquivalence() {
318        return Equivalences.identity();
319      }
320    },
321
322    WEAK {
323      @Override
324      <K, V> ValueReference<K, V> referenceValue(
325          Segment<K, V> segment, ReferenceEntry<K, V> entry, V value) {
326        return new WeakValueReference<K, V>(segment.valueReferenceQueue, value, entry);
327      }
328
329      @Override
330      Equivalence<Object> defaultEquivalence() {
331        return Equivalences.identity();
332      }
333    };
334
335    /**
336     * Creates a reference for the given value according to this value strength.
337     */
338    abstract <K, V> ValueReference<K, V> referenceValue(
339        Segment<K, V> segment, ReferenceEntry<K, V> entry, V value);
340
341    /**
342     * Returns the default equivalence strategy used to compare and hash keys or values referenced
343     * at this strength. This strategy will be used unless the user explicitly specifies an
344     * alternate strategy.
345     */
346    abstract Equivalence<Object> defaultEquivalence();
347  }
348
349  /**
350   * Creates new entries.
351   */
352  enum EntryFactory {
353    STRONG {
354      @Override
355      <K, V> ReferenceEntry<K, V> newEntry(
356          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
357        return new StrongEntry<K, V>(key, hash, next);
358      }
359    },
360    STRONG_EXPIRABLE {
361      @Override
362      <K, V> ReferenceEntry<K, V> newEntry(
363          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
364        return new StrongExpirableEntry<K, V>(key, hash, next);
365      }
366
367      @Override
368      <K, V> ReferenceEntry<K, V> copyEntry(
369          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
370        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
371        copyExpirableEntry(original, newEntry);
372        return newEntry;
373      }
374    },
375    STRONG_EVICTABLE {
376      @Override
377      <K, V> ReferenceEntry<K, V> newEntry(
378          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
379        return new StrongEvictableEntry<K, V>(key, hash, next);
380      }
381
382      @Override
383      <K, V> ReferenceEntry<K, V> copyEntry(
384          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
385        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
386        copyEvictableEntry(original, newEntry);
387        return newEntry;
388      }
389    },
390    STRONG_EXPIRABLE_EVICTABLE {
391      @Override
392      <K, V> ReferenceEntry<K, V> newEntry(
393          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
394        return new StrongExpirableEvictableEntry<K, V>(key, hash, next);
395      }
396
397      @Override
398      <K, V> ReferenceEntry<K, V> copyEntry(
399          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
400        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
401        copyExpirableEntry(original, newEntry);
402        copyEvictableEntry(original, newEntry);
403        return newEntry;
404      }
405    },
406
407    SOFT {
408      @Override
409      <K, V> ReferenceEntry<K, V> newEntry(
410          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
411        return new SoftEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
412      }
413    },
414    SOFT_EXPIRABLE {
415      @Override
416      <K, V> ReferenceEntry<K, V> newEntry(
417          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
418        return new SoftExpirableEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
419      }
420
421      @Override
422      <K, V> ReferenceEntry<K, V> copyEntry(
423          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
424        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
425        copyExpirableEntry(original, newEntry);
426        return newEntry;
427      }
428    },
429    SOFT_EVICTABLE {
430      @Override
431      <K, V> ReferenceEntry<K, V> newEntry(
432          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
433        return new SoftEvictableEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
434      }
435
436      @Override
437      <K, V> ReferenceEntry<K, V> copyEntry(
438          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
439        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
440        copyEvictableEntry(original, newEntry);
441        return newEntry;
442      }
443    },
444    SOFT_EXPIRABLE_EVICTABLE {
445      @Override
446      <K, V> ReferenceEntry<K, V> newEntry(
447          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
448        return new SoftExpirableEvictableEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
449      }
450
451      @Override
452      <K, V> ReferenceEntry<K, V> copyEntry(
453          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
454        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
455        copyExpirableEntry(original, newEntry);
456        copyEvictableEntry(original, newEntry);
457        return newEntry;
458      }
459    },
460
461    WEAK {
462      @Override
463      <K, V> ReferenceEntry<K, V> newEntry(
464          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
465        return new WeakEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
466      }
467    },
468    WEAK_EXPIRABLE {
469      @Override
470      <K, V> ReferenceEntry<K, V> newEntry(
471          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
472        return new WeakExpirableEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
473      }
474
475      @Override
476      <K, V> ReferenceEntry<K, V> copyEntry(
477          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
478        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
479        copyExpirableEntry(original, newEntry);
480        return newEntry;
481      }
482    },
483    WEAK_EVICTABLE {
484      @Override
485      <K, V> ReferenceEntry<K, V> newEntry(
486          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
487        return new WeakEvictableEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
488      }
489
490      @Override
491      <K, V> ReferenceEntry<K, V> copyEntry(
492          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
493        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
494        copyEvictableEntry(original, newEntry);
495        return newEntry;
496      }
497    },
498    WEAK_EXPIRABLE_EVICTABLE {
499      @Override
500      <K, V> ReferenceEntry<K, V> newEntry(
501          Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
502        return new WeakExpirableEvictableEntry<K, V>(segment.keyReferenceQueue, key, hash, next);
503      }
504
505      @Override
506      <K, V> ReferenceEntry<K, V> copyEntry(
507          Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
508        ReferenceEntry<K, V> newEntry = super.copyEntry(segment, original, newNext);
509        copyExpirableEntry(original, newEntry);
510        copyEvictableEntry(original, newEntry);
511        return newEntry;
512      }
513    };
514
515    /**
516     * Masks used to compute indices in the following table.
517     */
518    static final int EXPIRABLE_MASK = 1;
519    static final int EVICTABLE_MASK = 2;
520
521    /**
522     * Look-up table for factories. First dimension is the reference type. The second dimension is
523     * the result of OR-ing the feature masks.
524     */
525    static final EntryFactory[][] factories = {
526      { STRONG, STRONG_EXPIRABLE, STRONG_EVICTABLE, STRONG_EXPIRABLE_EVICTABLE },
527      { SOFT, SOFT_EXPIRABLE, SOFT_EVICTABLE, SOFT_EXPIRABLE_EVICTABLE },
528      { WEAK, WEAK_EXPIRABLE, WEAK_EVICTABLE, WEAK_EXPIRABLE_EVICTABLE }
529    };
530
531    static EntryFactory getFactory(Strength keyStrength, boolean expireAfterWrite,
532        boolean evictsBySize) {
533      int flags = (expireAfterWrite ? EXPIRABLE_MASK : 0) | (evictsBySize ? EVICTABLE_MASK : 0);
534      return factories[keyStrength.ordinal()][flags];
535    }
536
537    /**
538     * Creates a new entry.
539     *
540     * @param segment to create the entry for
541     * @param key of the entry
542     * @param hash of the key
543     * @param next entry in the same bucket
544     */
545    abstract <K, V> ReferenceEntry<K, V> newEntry(
546        Segment<K, V> segment, K key, int hash, @Nullable ReferenceEntry<K, V> next);
547
548    /**
549     * Copies an entry, assigning it a new {@code next} entry.
550     *
551     * @param original the entry to copy
552     * @param newNext entry in the same bucket
553     */
554    @GuardedBy("Segment.this")
555    <K, V> ReferenceEntry<K, V> copyEntry(
556        Segment<K, V> segment, ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
557      return newEntry(segment, original.getKey(), original.getHash(), newNext);
558    }
559
560    @GuardedBy("Segment.this")
561    <K, V> void copyExpirableEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newEntry) {
562      // TODO(fry): when we link values instead of entries this method can go
563      // away, as can connectExpirables, nullifyExpirable.
564      newEntry.setExpirationTime(original.getExpirationTime());
565
566      connectExpirables(original.getPreviousExpirable(), newEntry);
567      connectExpirables(newEntry, original.getNextExpirable());
568
569      nullifyExpirable(original);
570    }
571
572    @GuardedBy("Segment.this")
573    <K, V> void copyEvictableEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newEntry) {
574      // TODO(fry): when we link values instead of entries this method can go
575      // away, as can connectEvictables, nullifyEvictable.
576      connectEvictables(original.getPreviousEvictable(), newEntry);
577      connectEvictables(newEntry, original.getNextEvictable());
578
579      nullifyEvictable(original);
580    }
581  }
582
583  /**
584   * A reference to a value.
585   */
586  interface ValueReference<K, V> {
587    /**
588     * Gets the value. Does not block or throw exceptions.
589     */
590    V get();
591
592    /**
593     * Waits for a value that may still be computing. Unlike get(), this method can block (in the
594     * case of FutureValueReference).
595     *
596     * @throws ExecutionException if the computing thread throws an exception
597     */
598    V waitForValue() throws ExecutionException;
599
600    /**
601     * Returns the entry associated with this value reference, or {@code null} if this value
602     * reference is independent of any entry.
603     */
604    ReferenceEntry<K, V> getEntry();
605
606    /**
607     * Creates a copy of this reference for the given entry.
608     */
609    ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry);
610
611    /**
612     * Clears this reference object.
613     *
614     * @param newValue the new value reference which will replace this one; this is only used during
615     *     computation to immediately notify blocked threads of the new value
616     */
617    void clear(@Nullable ValueReference<K, V> newValue);
618
619    /**
620     * Returns {@code true} if the value type is a computing reference (regardless of whether or not
621     * computation has completed). This is necessary to distiguish between partially-collected
622     * entries and computing entries, which need to be cleaned up differently.
623     */
624    boolean isComputingReference();
625  }
626
627  /**
628   * Placeholder. Indicates that the value hasn't been set yet.
629   */
630  static final ValueReference<Object, Object> UNSET = new ValueReference<Object, Object>() {
631    @Override
632    public Object get() {
633      return null;
634    }
635
636    @Override
637    public ReferenceEntry<Object, Object> getEntry() {
638      return null;
639    }
640
641    @Override
642    public ValueReference<Object, Object> copyFor(
643        ReferenceQueue<Object> queue, ReferenceEntry<Object, Object> entry) {
644      return this;
645    }
646
647    @Override
648    public boolean isComputingReference() {
649      return false;
650    }
651
652    @Override
653    public Object waitForValue() {
654      return null;
655    }
656
657    @Override
658    public void clear(ValueReference<Object, Object> newValue) {}
659  };
660
661  /**
662   * Singleton placeholder that indicates a value is being computed.
663   */
664  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value
665  static <K, V> ValueReference<K, V> unset() {
666    return (ValueReference<K, V>) UNSET;
667  }
668
669  /**
670   * An entry in a reference map.
671   *
672   * Entries in the map can be in the following states:
673   *
674   * Valid:
675   * - Live: valid key/value are set
676   * - Computing: computation is pending
677   *
678   * Invalid:
679   * - Expired: time expired (key/value may still be set)
680   * - Collected: key/value was partially collected, but not yet cleaned up
681   */
682  interface ReferenceEntry<K, V> {
683    /**
684     * Gets the value reference from this entry.
685     */
686    ValueReference<K, V> getValueReference();
687
688    /**
689     * Sets the value reference for this entry.
690     */
691    void setValueReference(ValueReference<K, V> valueReference);
692
693    /**
694     * Gets the next entry in the chain.
695     */
696    ReferenceEntry<K, V> getNext();
697
698    /**
699     * Gets the entry's hash.
700     */
701    int getHash();
702
703    /**
704     * Gets the key for this entry.
705     */
706    K getKey();
707
708    /*
709     * Used by entries that are expirable. Expirable entries are maintained in a doubly-linked list.
710     * New entries are added at the tail of the list at write time; stale entries are expired from
711     * the head of the list.
712     */
713
714    /**
715     * Gets the entry expiration time in ns.
716     */
717    long getExpirationTime();
718
719    /**
720     * Sets the entry expiration time in ns.
721     */
722    void setExpirationTime(long time);
723
724    /**
725     * Gets the next entry in the recency list.
726     */
727    ReferenceEntry<K, V> getNextExpirable();
728
729    /**
730     * Sets the next entry in the recency list.
731     */
732    void setNextExpirable(ReferenceEntry<K, V> next);
733
734    /**
735     * Gets the previous entry in the recency list.
736     */
737    ReferenceEntry<K, V> getPreviousExpirable();
738
739    /**
740     * Sets the previous entry in the recency list.
741     */
742    void setPreviousExpirable(ReferenceEntry<K, V> previous);
743
744    /*
745     * Implemented by entries that are evictable. Evictable entries are maintained in a
746     * doubly-linked list. New entries are added at the tail of the list at write time and stale
747     * entries are expired from the head of the list.
748     */
749
750    /**
751     * Gets the next entry in the recency list.
752     */
753    ReferenceEntry<K, V> getNextEvictable();
754
755    /**
756     * Sets the next entry in the recency list.
757     */
758    void setNextEvictable(ReferenceEntry<K, V> next);
759
760    /**
761     * Gets the previous entry in the recency list.
762     */
763    ReferenceEntry<K, V> getPreviousEvictable();
764
765    /**
766     * Sets the previous entry in the recency list.
767     */
768    void setPreviousEvictable(ReferenceEntry<K, V> previous);
769  }
770
771  private enum NullEntry implements ReferenceEntry<Object, Object> {
772    INSTANCE;
773
774    @Override
775    public ValueReference<Object, Object> getValueReference() {
776      return null;
777    }
778
779    @Override
780    public void setValueReference(ValueReference<Object, Object> valueReference) {}
781
782    @Override
783    public ReferenceEntry<Object, Object> getNext() {
784      return null;
785    }
786
787    @Override
788    public int getHash() {
789      return 0;
790    }
791
792    @Override
793    public Object getKey() {
794      return null;
795    }
796
797    @Override
798    public long getExpirationTime() {
799      return 0;
800    }
801
802    @Override
803    public void setExpirationTime(long time) {}
804
805    @Override
806    public ReferenceEntry<Object, Object> getNextExpirable() {
807      return this;
808    }
809
810    @Override
811    public void setNextExpirable(ReferenceEntry<Object, Object> next) {}
812
813    @Override
814    public ReferenceEntry<Object, Object> getPreviousExpirable() {
815      return this;
816    }
817
818    @Override
819    public void setPreviousExpirable(ReferenceEntry<Object, Object> previous) {}
820
821    @Override
822    public ReferenceEntry<Object, Object> getNextEvictable() {
823      return this;
824    }
825
826    @Override
827    public void setNextEvictable(ReferenceEntry<Object, Object> next) {}
828
829    @Override
830    public ReferenceEntry<Object, Object> getPreviousEvictable() {
831      return this;
832    }
833
834    @Override
835    public void setPreviousEvictable(ReferenceEntry<Object, Object> previous) {}
836  }
837
838  static abstract class AbstractReferenceEntry<K, V> implements ReferenceEntry<K, V> {
839    @Override
840    public ValueReference<K, V> getValueReference() {
841      throw new UnsupportedOperationException();
842    }
843
844    @Override
845    public void setValueReference(ValueReference<K, V> valueReference) {
846      throw new UnsupportedOperationException();
847    }
848
849    @Override
850    public ReferenceEntry<K, V> getNext() {
851      throw new UnsupportedOperationException();
852    }
853
854    @Override
855    public int getHash() {
856      throw new UnsupportedOperationException();
857    }
858
859    @Override
860    public K getKey() {
861      throw new UnsupportedOperationException();
862    }
863
864    @Override
865    public long getExpirationTime() {
866      throw new UnsupportedOperationException();
867    }
868
869    @Override
870    public void setExpirationTime(long time) {
871      throw new UnsupportedOperationException();
872    }
873
874    @Override
875    public ReferenceEntry<K, V> getNextExpirable() {
876      throw new UnsupportedOperationException();
877    }
878
879    @Override
880    public void setNextExpirable(ReferenceEntry<K, V> next) {
881      throw new UnsupportedOperationException();
882    }
883
884    @Override
885    public ReferenceEntry<K, V> getPreviousExpirable() {
886      throw new UnsupportedOperationException();
887    }
888
889    @Override
890    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
891      throw new UnsupportedOperationException();
892    }
893
894    @Override
895    public ReferenceEntry<K, V> getNextEvictable() {
896      throw new UnsupportedOperationException();
897    }
898
899    @Override
900    public void setNextEvictable(ReferenceEntry<K, V> next) {
901      throw new UnsupportedOperationException();
902    }
903
904    @Override
905    public ReferenceEntry<K, V> getPreviousEvictable() {
906      throw new UnsupportedOperationException();
907    }
908
909    @Override
910    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
911      throw new UnsupportedOperationException();
912    }
913  }
914
915  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value
916  static <K, V> ReferenceEntry<K, V> nullEntry() {
917    return (ReferenceEntry<K, V>) NullEntry.INSTANCE;
918  }
919
920  static final Queue<? extends Object> DISCARDING_QUEUE = new AbstractQueue<Object>() {
921    @Override
922    public boolean offer(Object o) {
923      return true;
924    }
925
926    @Override
927    public Object peek() {
928      return null;
929    }
930
931    @Override
932    public Object poll() {
933      return null;
934    }
935
936    @Override
937    public int size() {
938      return 0;
939    }
940
941    @Override
942    public Iterator<Object> iterator() {
943      return Iterators.emptyIterator();
944    }
945  };
946
947  /**
948   * Queue that discards all elements.
949   */
950  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value
951  static <E> Queue<E> discardingQueue() {
952    return (Queue) DISCARDING_QUEUE;
953  }
954
955  /*
956   * Note: All of this duplicate code sucks, but it saves a lot of memory. If only Java had mixins!
957   * To maintain this code, make a change for the strong reference type. Then, cut and paste, and
958   * replace "Strong" with "Soft" or "Weak" within the pasted text. The primary difference is that
959   * strong entries store the key reference directly while soft and weak entries delegate to their
960   * respective superclasses.
961   */
962
963  /**
964   * Used for strongly-referenced keys.
965   */
966  static class StrongEntry<K, V> implements ReferenceEntry<K, V> {
967    final K key;
968
969    StrongEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
970      this.key = key;
971      this.hash = hash;
972      this.next = next;
973    }
974
975    @Override
976    public K getKey() {
977      return this.key;
978    }
979
980    // null expiration
981
982    @Override
983    public long getExpirationTime() {
984      throw new UnsupportedOperationException();
985    }
986
987    @Override
988    public void setExpirationTime(long time) {
989      throw new UnsupportedOperationException();
990    }
991
992    @Override
993    public ReferenceEntry<K, V> getNextExpirable() {
994      throw new UnsupportedOperationException();
995    }
996
997    @Override
998    public void setNextExpirable(ReferenceEntry<K, V> next) {
999      throw new UnsupportedOperationException();
1000    }
1001
1002    @Override
1003    public ReferenceEntry<K, V> getPreviousExpirable() {
1004      throw new UnsupportedOperationException();
1005    }
1006
1007    @Override
1008    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1009      throw new UnsupportedOperationException();
1010    }
1011
1012    // null eviction
1013
1014    @Override
1015    public ReferenceEntry<K, V> getNextEvictable() {
1016      throw new UnsupportedOperationException();
1017    }
1018
1019    @Override
1020    public void setNextEvictable(ReferenceEntry<K, V> next) {
1021      throw new UnsupportedOperationException();
1022    }
1023
1024    @Override
1025    public ReferenceEntry<K, V> getPreviousEvictable() {
1026      throw new UnsupportedOperationException();
1027    }
1028
1029    @Override
1030    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1031      throw new UnsupportedOperationException();
1032    }
1033
1034    // The code below is exactly the same for each entry type.
1035
1036    final int hash;
1037    final ReferenceEntry<K, V> next;
1038    volatile ValueReference<K, V> valueReference = unset();
1039
1040    @Override
1041    public ValueReference<K, V> getValueReference() {
1042      return valueReference;
1043    }
1044
1045    @Override
1046    public void setValueReference(ValueReference<K, V> valueReference) {
1047      ValueReference<K, V> previous = this.valueReference;
1048      this.valueReference = valueReference;
1049      previous.clear(valueReference);
1050    }
1051
1052    @Override
1053    public int getHash() {
1054      return hash;
1055    }
1056
1057    @Override
1058    public ReferenceEntry<K, V> getNext() {
1059      return next;
1060    }
1061  }
1062
1063  static final class StrongExpirableEntry<K, V> extends StrongEntry<K, V>
1064      implements ReferenceEntry<K, V> {
1065    StrongExpirableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1066      super(key, hash, next);
1067    }
1068
1069    // The code below is exactly the same for each expirable entry type.
1070
1071    volatile long time = Long.MAX_VALUE;
1072
1073    @Override
1074    public long getExpirationTime() {
1075      return time;
1076    }
1077
1078    @Override
1079    public void setExpirationTime(long time) {
1080      this.time = time;
1081    }
1082
1083    @GuardedBy("Segment.this")
1084    ReferenceEntry<K, V> nextExpirable = nullEntry();
1085
1086    @Override
1087    public ReferenceEntry<K, V> getNextExpirable() {
1088      return nextExpirable;
1089    }
1090
1091    @Override
1092    public void setNextExpirable(ReferenceEntry<K, V> next) {
1093      this.nextExpirable = next;
1094    }
1095
1096    @GuardedBy("Segment.this")
1097    ReferenceEntry<K, V> previousExpirable = nullEntry();
1098
1099    @Override
1100    public ReferenceEntry<K, V> getPreviousExpirable() {
1101      return previousExpirable;
1102    }
1103
1104    @Override
1105    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1106      this.previousExpirable = previous;
1107    }
1108  }
1109
1110  static final class StrongEvictableEntry<K, V>
1111      extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
1112    StrongEvictableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1113      super(key, hash, next);
1114    }
1115
1116    // The code below is exactly the same for each evictable entry type.
1117
1118    @GuardedBy("Segment.this")
1119    ReferenceEntry<K, V> nextEvictable = nullEntry();
1120
1121    @Override
1122    public ReferenceEntry<K, V> getNextEvictable() {
1123      return nextEvictable;
1124    }
1125
1126    @Override
1127    public void setNextEvictable(ReferenceEntry<K, V> next) {
1128      this.nextEvictable = next;
1129    }
1130
1131    @GuardedBy("Segment.this")
1132    ReferenceEntry<K, V> previousEvictable = nullEntry();
1133
1134    @Override
1135    public ReferenceEntry<K, V> getPreviousEvictable() {
1136      return previousEvictable;
1137    }
1138
1139    @Override
1140    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1141      this.previousEvictable = previous;
1142    }
1143  }
1144
1145  static final class StrongExpirableEvictableEntry<K, V>
1146      extends StrongEntry<K, V> implements ReferenceEntry<K, V> {
1147    StrongExpirableEvictableEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1148      super(key, hash, next);
1149    }
1150
1151    // The code below is exactly the same for each expirable entry type.
1152
1153    volatile long time = Long.MAX_VALUE;
1154
1155    @Override
1156    public long getExpirationTime() {
1157      return time;
1158    }
1159
1160    @Override
1161    public void setExpirationTime(long time) {
1162      this.time = time;
1163    }
1164
1165    @GuardedBy("Segment.this")
1166    ReferenceEntry<K, V> nextExpirable = nullEntry();
1167
1168    @Override
1169    public ReferenceEntry<K, V> getNextExpirable() {
1170      return nextExpirable;
1171    }
1172
1173    @Override
1174    public void setNextExpirable(ReferenceEntry<K, V> next) {
1175      this.nextExpirable = next;
1176    }
1177
1178    @GuardedBy("Segment.this")
1179    ReferenceEntry<K, V> previousExpirable = nullEntry();
1180
1181    @Override
1182    public ReferenceEntry<K, V> getPreviousExpirable() {
1183      return previousExpirable;
1184    }
1185
1186    @Override
1187    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1188      this.previousExpirable = previous;
1189    }
1190
1191    // The code below is exactly the same for each evictable entry type.
1192
1193    @GuardedBy("Segment.this")
1194    ReferenceEntry<K, V> nextEvictable = nullEntry();
1195
1196    @Override
1197    public ReferenceEntry<K, V> getNextEvictable() {
1198      return nextEvictable;
1199    }
1200
1201    @Override
1202    public void setNextEvictable(ReferenceEntry<K, V> next) {
1203      this.nextEvictable = next;
1204    }
1205
1206    @GuardedBy("Segment.this")
1207    ReferenceEntry<K, V> previousEvictable = nullEntry();
1208
1209    @Override
1210    public ReferenceEntry<K, V> getPreviousEvictable() {
1211      return previousEvictable;
1212    }
1213
1214    @Override
1215    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1216      this.previousEvictable = previous;
1217    }
1218  }
1219
1220  /**
1221   * Used for softly-referenced keys.
1222   */
1223  static class SoftEntry<K, V> extends SoftReference<K> implements ReferenceEntry<K, V> {
1224    SoftEntry(ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1225      super(key, queue);
1226      this.hash = hash;
1227      this.next = next;
1228    }
1229
1230    @Override
1231    public K getKey() {
1232      return get();
1233    }
1234
1235    // null expiration
1236    @Override
1237    public long getExpirationTime() {
1238      throw new UnsupportedOperationException();
1239    }
1240
1241    @Override
1242    public void setExpirationTime(long time) {
1243      throw new UnsupportedOperationException();
1244    }
1245
1246    @Override
1247    public ReferenceEntry<K, V> getNextExpirable() {
1248      throw new UnsupportedOperationException();
1249    }
1250
1251    @Override
1252    public void setNextExpirable(ReferenceEntry<K, V> next) {
1253      throw new UnsupportedOperationException();
1254    }
1255
1256    @Override
1257    public ReferenceEntry<K, V> getPreviousExpirable() {
1258      throw new UnsupportedOperationException();
1259    }
1260
1261    @Override
1262    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1263      throw new UnsupportedOperationException();
1264    }
1265
1266    // null eviction
1267
1268    @Override
1269    public ReferenceEntry<K, V> getNextEvictable() {
1270      throw new UnsupportedOperationException();
1271    }
1272
1273    @Override
1274    public void setNextEvictable(ReferenceEntry<K, V> next) {
1275      throw new UnsupportedOperationException();
1276    }
1277
1278    @Override
1279    public ReferenceEntry<K, V> getPreviousEvictable() {
1280      throw new UnsupportedOperationException();
1281    }
1282
1283    @Override
1284    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1285      throw new UnsupportedOperationException();
1286    }
1287
1288    // The code below is exactly the same for each entry type.
1289
1290    final int hash;
1291    final ReferenceEntry<K, V> next;
1292    volatile ValueReference<K, V> valueReference = unset();
1293
1294    @Override
1295    public ValueReference<K, V> getValueReference() {
1296      return valueReference;
1297    }
1298
1299    @Override
1300    public void setValueReference(ValueReference<K, V> valueReference) {
1301      ValueReference<K, V> previous = this.valueReference;
1302      this.valueReference = valueReference;
1303      previous.clear(valueReference);
1304    }
1305
1306    @Override
1307    public int getHash() {
1308      return hash;
1309    }
1310
1311    @Override
1312    public ReferenceEntry<K, V> getNext() {
1313      return next;
1314    }
1315  }
1316
1317  static final class SoftExpirableEntry<K, V>
1318      extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
1319    SoftExpirableEntry(
1320        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1321      super(queue, key, hash, next);
1322    }
1323
1324    // The code below is exactly the same for each expirable entry type.
1325
1326    volatile long time = Long.MAX_VALUE;
1327
1328    @Override
1329    public long getExpirationTime() {
1330      return time;
1331    }
1332
1333    @Override
1334    public void setExpirationTime(long time) {
1335      this.time = time;
1336    }
1337
1338    @GuardedBy("Segment.this")
1339    ReferenceEntry<K, V> nextExpirable = nullEntry();
1340
1341    @Override
1342    public ReferenceEntry<K, V> getNextExpirable() {
1343      return nextExpirable;
1344    }
1345
1346    @Override
1347    public void setNextExpirable(ReferenceEntry<K, V> next) {
1348      this.nextExpirable = next;
1349    }
1350
1351    @GuardedBy("Segment.this")
1352    ReferenceEntry<K, V> previousExpirable = nullEntry();
1353
1354    @Override
1355    public ReferenceEntry<K, V> getPreviousExpirable() {
1356      return previousExpirable;
1357    }
1358
1359    @Override
1360    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1361      this.previousExpirable = previous;
1362    }
1363  }
1364
1365  static final class SoftEvictableEntry<K, V>
1366      extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
1367    SoftEvictableEntry(
1368        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1369      super(queue, key, hash, next);
1370    }
1371
1372    // The code below is exactly the same for each evictable entry type.
1373
1374    @GuardedBy("Segment.this")
1375    ReferenceEntry<K, V> nextEvictable = nullEntry();
1376
1377    @Override
1378    public ReferenceEntry<K, V> getNextEvictable() {
1379      return nextEvictable;
1380    }
1381
1382    @Override
1383    public void setNextEvictable(ReferenceEntry<K, V> next) {
1384      this.nextEvictable = next;
1385    }
1386
1387    @GuardedBy("Segment.this")
1388    ReferenceEntry<K, V> previousEvictable = nullEntry();
1389
1390    @Override
1391    public ReferenceEntry<K, V> getPreviousEvictable() {
1392      return previousEvictable;
1393    }
1394
1395    @Override
1396    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1397      this.previousEvictable = previous;
1398    }
1399  }
1400
1401  static final class SoftExpirableEvictableEntry<K, V>
1402      extends SoftEntry<K, V> implements ReferenceEntry<K, V> {
1403    SoftExpirableEvictableEntry(
1404        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1405      super(queue, key, hash, next);
1406    }
1407
1408    // The code below is exactly the same for each expirable entry type.
1409
1410    volatile long time = Long.MAX_VALUE;
1411
1412    @Override
1413    public long getExpirationTime() {
1414      return time;
1415    }
1416
1417    @Override
1418    public void setExpirationTime(long time) {
1419      this.time = time;
1420    }
1421
1422    @GuardedBy("Segment.this")
1423    ReferenceEntry<K, V> nextExpirable = nullEntry();
1424
1425    @Override
1426    public ReferenceEntry<K, V> getNextExpirable() {
1427      return nextExpirable;
1428    }
1429
1430    @Override
1431    public void setNextExpirable(ReferenceEntry<K, V> next) {
1432      this.nextExpirable = next;
1433    }
1434
1435    @GuardedBy("Segment.this")
1436    ReferenceEntry<K, V> previousExpirable = nullEntry();
1437
1438    @Override
1439    public ReferenceEntry<K, V> getPreviousExpirable() {
1440      return previousExpirable;
1441    }
1442
1443    @Override
1444    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1445      this.previousExpirable = previous;
1446    }
1447
1448    // The code below is exactly the same for each evictable entry type.
1449
1450    @GuardedBy("Segment.this")
1451    ReferenceEntry<K, V> nextEvictable = nullEntry();
1452
1453    @Override
1454    public ReferenceEntry<K, V> getNextEvictable() {
1455      return nextEvictable;
1456    }
1457
1458    @Override
1459    public void setNextEvictable(ReferenceEntry<K, V> next) {
1460      this.nextEvictable = next;
1461    }
1462
1463    @GuardedBy("Segment.this")
1464    ReferenceEntry<K, V> previousEvictable = nullEntry();
1465
1466    @Override
1467    public ReferenceEntry<K, V> getPreviousEvictable() {
1468      return previousEvictable;
1469    }
1470
1471    @Override
1472    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1473      this.previousEvictable = previous;
1474    }
1475  }
1476
1477  /**
1478   * Used for weakly-referenced keys.
1479   */
1480  static class WeakEntry<K, V> extends WeakReference<K> implements ReferenceEntry<K, V> {
1481    WeakEntry(ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1482      super(key, queue);
1483      this.hash = hash;
1484      this.next = next;
1485    }
1486
1487    @Override
1488    public K getKey() {
1489      return get();
1490    }
1491
1492    // null expiration
1493
1494    @Override
1495    public long getExpirationTime() {
1496      throw new UnsupportedOperationException();
1497    }
1498
1499    @Override
1500    public void setExpirationTime(long time) {
1501      throw new UnsupportedOperationException();
1502    }
1503
1504    @Override
1505    public ReferenceEntry<K, V> getNextExpirable() {
1506      throw new UnsupportedOperationException();
1507    }
1508
1509    @Override
1510    public void setNextExpirable(ReferenceEntry<K, V> next) {
1511      throw new UnsupportedOperationException();
1512    }
1513
1514    @Override
1515    public ReferenceEntry<K, V> getPreviousExpirable() {
1516      throw new UnsupportedOperationException();
1517    }
1518
1519    @Override
1520    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1521      throw new UnsupportedOperationException();
1522    }
1523
1524    // null eviction
1525
1526    @Override
1527    public ReferenceEntry<K, V> getNextEvictable() {
1528      throw new UnsupportedOperationException();
1529    }
1530
1531    @Override
1532    public void setNextEvictable(ReferenceEntry<K, V> next) {
1533      throw new UnsupportedOperationException();
1534    }
1535
1536    @Override
1537    public ReferenceEntry<K, V> getPreviousEvictable() {
1538      throw new UnsupportedOperationException();
1539    }
1540
1541    @Override
1542    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1543      throw new UnsupportedOperationException();
1544    }
1545
1546    // The code below is exactly the same for each entry type.
1547
1548    final int hash;
1549    final ReferenceEntry<K, V> next;
1550    volatile ValueReference<K, V> valueReference = unset();
1551
1552    @Override
1553    public ValueReference<K, V> getValueReference() {
1554      return valueReference;
1555    }
1556
1557    @Override
1558    public void setValueReference(ValueReference<K, V> valueReference) {
1559      ValueReference<K, V> previous = this.valueReference;
1560      this.valueReference = valueReference;
1561      previous.clear(valueReference);
1562    }
1563
1564    @Override
1565    public int getHash() {
1566      return hash;
1567    }
1568
1569    @Override
1570    public ReferenceEntry<K, V> getNext() {
1571      return next;
1572    }
1573  }
1574
1575  static final class WeakExpirableEntry<K, V>
1576      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
1577    WeakExpirableEntry(
1578        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1579      super(queue, key, hash, next);
1580    }
1581
1582    // The code below is exactly the same for each expirable entry type.
1583
1584    volatile long time = Long.MAX_VALUE;
1585
1586    @Override
1587    public long getExpirationTime() {
1588      return time;
1589    }
1590
1591    @Override
1592    public void setExpirationTime(long time) {
1593      this.time = time;
1594    }
1595
1596    @GuardedBy("Segment.this")
1597    ReferenceEntry<K, V> nextExpirable = nullEntry();
1598
1599    @Override
1600    public ReferenceEntry<K, V> getNextExpirable() {
1601      return nextExpirable;
1602    }
1603
1604    @Override
1605    public void setNextExpirable(ReferenceEntry<K, V> next) {
1606      this.nextExpirable = next;
1607    }
1608
1609    @GuardedBy("Segment.this")
1610    ReferenceEntry<K, V> previousExpirable = nullEntry();
1611
1612    @Override
1613    public ReferenceEntry<K, V> getPreviousExpirable() {
1614      return previousExpirable;
1615    }
1616
1617    @Override
1618    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1619      this.previousExpirable = previous;
1620    }
1621  }
1622
1623  static final class WeakEvictableEntry<K, V>
1624      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
1625    WeakEvictableEntry(
1626        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1627      super(queue, key, hash, next);
1628    }
1629
1630    // The code below is exactly the same for each evictable entry type.
1631
1632    @GuardedBy("Segment.this")
1633    ReferenceEntry<K, V> nextEvictable = nullEntry();
1634
1635    @Override
1636    public ReferenceEntry<K, V> getNextEvictable() {
1637      return nextEvictable;
1638    }
1639
1640    @Override
1641    public void setNextEvictable(ReferenceEntry<K, V> next) {
1642      this.nextEvictable = next;
1643    }
1644
1645    @GuardedBy("Segment.this")
1646    ReferenceEntry<K, V> previousEvictable = nullEntry();
1647
1648    @Override
1649    public ReferenceEntry<K, V> getPreviousEvictable() {
1650      return previousEvictable;
1651    }
1652
1653    @Override
1654    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1655      this.previousEvictable = previous;
1656    }
1657  }
1658
1659  static final class WeakExpirableEvictableEntry<K, V>
1660      extends WeakEntry<K, V> implements ReferenceEntry<K, V> {
1661    WeakExpirableEvictableEntry(
1662        ReferenceQueue<K> queue, K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1663      super(queue, key, hash, next);
1664    }
1665
1666    // The code below is exactly the same for each expirable entry type.
1667
1668    volatile long time = Long.MAX_VALUE;
1669
1670    @Override
1671    public long getExpirationTime() {
1672      return time;
1673    }
1674
1675    @Override
1676    public void setExpirationTime(long time) {
1677      this.time = time;
1678    }
1679
1680    @GuardedBy("Segment.this")
1681    ReferenceEntry<K, V> nextExpirable = nullEntry();
1682
1683    @Override
1684    public ReferenceEntry<K, V> getNextExpirable() {
1685      return nextExpirable;
1686    }
1687
1688    @Override
1689    public void setNextExpirable(ReferenceEntry<K, V> next) {
1690      this.nextExpirable = next;
1691    }
1692
1693    @GuardedBy("Segment.this")
1694    ReferenceEntry<K, V> previousExpirable = nullEntry();
1695
1696    @Override
1697    public ReferenceEntry<K, V> getPreviousExpirable() {
1698      return previousExpirable;
1699    }
1700
1701    @Override
1702    public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
1703      this.previousExpirable = previous;
1704    }
1705
1706    // The code below is exactly the same for each evictable entry type.
1707
1708    @GuardedBy("Segment.this")
1709    ReferenceEntry<K, V> nextEvictable = nullEntry();
1710
1711    @Override
1712    public ReferenceEntry<K, V> getNextEvictable() {
1713      return nextEvictable;
1714    }
1715
1716    @Override
1717    public void setNextEvictable(ReferenceEntry<K, V> next) {
1718      this.nextEvictable = next;
1719    }
1720
1721    @GuardedBy("Segment.this")
1722    ReferenceEntry<K, V> previousEvictable = nullEntry();
1723
1724    @Override
1725    public ReferenceEntry<K, V> getPreviousEvictable() {
1726      return previousEvictable;
1727    }
1728
1729    @Override
1730    public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
1731      this.previousEvictable = previous;
1732    }
1733  }
1734
1735  /**
1736   * References a weak value.
1737   */
1738  static final class WeakValueReference<K, V>
1739      extends WeakReference<V> implements ValueReference<K, V> {
1740    final ReferenceEntry<K, V> entry;
1741
1742    WeakValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
1743      super(referent, queue);
1744      this.entry = entry;
1745    }
1746
1747    @Override
1748    public ReferenceEntry<K, V> getEntry() {
1749      return entry;
1750    }
1751
1752    @Override
1753    public void clear(ValueReference<K, V> newValue) {
1754      clear();
1755    }
1756
1757    @Override
1758    public ValueReference<K, V> copyFor(
1759        ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
1760      return new WeakValueReference<K, V>(queue, get(), entry);
1761    }
1762
1763    @Override
1764    public boolean isComputingReference() {
1765      return false;
1766    }
1767
1768    @Override
1769    public V waitForValue() {
1770      return get();
1771    }
1772  }
1773
1774  /**
1775   * References a soft value.
1776   */
1777  static final class SoftValueReference<K, V>
1778      extends SoftReference<V> implements ValueReference<K, V> {
1779    final ReferenceEntry<K, V> entry;
1780
1781    SoftValueReference(ReferenceQueue<V> queue, V referent, ReferenceEntry<K, V> entry) {
1782      super(referent, queue);
1783      this.entry = entry;
1784    }
1785
1786    @Override
1787    public ReferenceEntry<K, V> getEntry() {
1788      return entry;
1789    }
1790
1791    @Override
1792    public void clear(ValueReference<K, V> newValue) {
1793      clear();
1794    }
1795
1796    @Override
1797    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
1798      return new SoftValueReference<K, V>(queue, get(), entry);
1799    }
1800
1801    @Override
1802    public boolean isComputingReference() {
1803      return false;
1804    }
1805
1806    @Override
1807    public V waitForValue() {
1808      return get();
1809    }
1810  }
1811
1812  /**
1813   * References a strong value.
1814   */
1815  static final class StrongValueReference<K, V> implements ValueReference<K, V> {
1816    final V referent;
1817
1818    StrongValueReference(V referent) {
1819      this.referent = referent;
1820    }
1821
1822    @Override
1823    public V get() {
1824      return referent;
1825    }
1826
1827    @Override
1828    public ReferenceEntry<K, V> getEntry() {
1829      return null;
1830    }
1831
1832    @Override
1833    public ValueReference<K, V> copyFor(ReferenceQueue<V> queue, ReferenceEntry<K, V> entry) {
1834      return this;
1835    }
1836
1837    @Override
1838    public boolean isComputingReference() {
1839      return false;
1840    }
1841
1842    @Override
1843    public V waitForValue() {
1844      return get();
1845    }
1846
1847    @Override
1848    public void clear(ValueReference<K, V> newValue) {}
1849  }
1850
1851  /**
1852   * Applies a supplemental hash function to a given hash code, which defends against poor quality
1853   * hash functions. This is critical when the concurrent hash map uses power-of-two length hash
1854   * tables, that otherwise encounter collisions for hash codes that do not differ in lower or
1855   * upper bits.
1856   *
1857   * @param h hash code
1858   */
1859  static int rehash(int h) {
1860    // Spread bits to regularize both segment and index locations,
1861    // using variant of single-word Wang/Jenkins hash.
1862    // TODO(kevinb): use Hashing/move this to Hashing?
1863    h += (h << 15) ^ 0xffffcd7d;
1864    h ^= (h >>> 10);
1865    h += (h << 3);
1866    h ^= (h >>> 6);
1867    h += (h << 2) + (h << 14);
1868    return h ^ (h >>> 16);
1869  }
1870
1871  /**
1872   * This method is a convenience for testing. Code should call {@link Segment#newEntry} directly.
1873   */
1874  @GuardedBy("Segment.this")
1875  @VisibleForTesting
1876  ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
1877    return segmentFor(hash).newEntry(key, hash, next);
1878  }
1879
1880  /**
1881   * This method is a convenience for testing. Code should call {@link Segment#copyEntry} directly.
1882   */
1883  @GuardedBy("Segment.this")
1884  @VisibleForTesting
1885  ReferenceEntry<K, V> copyEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
1886    int hash = original.getHash();
1887    return segmentFor(hash).copyEntry(original, newNext);
1888  }
1889
1890  /**
1891   * This method is a convenience for testing. Code should call {@link Segment#setValue} instead.
1892   */
1893  @GuardedBy("Segment.this")
1894  @VisibleForTesting
1895  ValueReference<K, V> newValueReference(ReferenceEntry<K, V> entry, V value) {
1896    int hash = entry.getHash();
1897    return valueStrength.referenceValue(segmentFor(hash), entry, value);
1898  }
1899
1900  int hash(Object key) {
1901    int h = keyEquivalence.hash(key);
1902    return rehash(h);
1903  }
1904
1905  void reclaimValue(ValueReference<K, V> valueReference) {
1906    ReferenceEntry<K, V> entry = valueReference.getEntry();
1907    int hash = entry.getHash();
1908    segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference);
1909  }
1910
1911  void reclaimKey(ReferenceEntry<K, V> entry) {
1912    int hash = entry.getHash();
1913    segmentFor(hash).reclaimKey(entry, hash);
1914  }
1915
1916  /**
1917   * This method is a convenience for testing. Code should call {@link Segment#getLiveValue}
1918   * instead.
1919   */
1920  @VisibleForTesting
1921  boolean isLive(ReferenceEntry<K, V> entry) {
1922    return segmentFor(entry.getHash()).getLiveValue(entry) != null;
1923  }
1924
1925  /**
1926   * Returns the segment that should be used for a key with the given hash.
1927   *
1928   * @param hash the hash code for the key
1929   * @return the segment
1930   */
1931  Segment<K, V> segmentFor(int hash) {
1932    // TODO(fry): Lazily create segments?
1933    return segments[(hash >>> segmentShift) & segmentMask];
1934  }
1935
1936  Segment<K, V> createSegment(int initialCapacity, int maxSegmentSize) {
1937    return new Segment<K, V>(this, initialCapacity, maxSegmentSize);
1938  }
1939
1940  /**
1941   * Gets the value from an entry. Returns {@code null} if the entry is invalid,
1942   * partially-collected, computing, or expired. Unlike {@link Segment#getLiveValue} this method
1943   * does not attempt to clean up stale entries.
1944   */
1945  V getLiveValue(ReferenceEntry<K, V> entry) {
1946    if (entry.getKey() == null) {
1947      return null;
1948    }
1949    V value = entry.getValueReference().get();
1950    if (value == null) {
1951      return null;
1952    }
1953
1954    if (expires() && isExpired(entry)) {
1955      return null;
1956    }
1957    return value;
1958  }
1959
1960  // expiration
1961
1962  /**
1963   * Returns {@code true} if the entry has expired.
1964   */
1965  boolean isExpired(ReferenceEntry<K, V> entry) {
1966    return isExpired(entry, ticker.read());
1967  }
1968
1969  /**
1970   * Returns {@code true} if the entry has expired.
1971   */
1972  boolean isExpired(ReferenceEntry<K, V> entry, long now) {
1973    // if the expiration time had overflowed, this "undoes" the overflow
1974    return now - entry.getExpirationTime() > 0;
1975  }
1976
1977  @GuardedBy("Segment.this")
1978  static <K, V> void connectExpirables(ReferenceEntry<K, V> previous, ReferenceEntry<K, V> next) {
1979    previous.setNextExpirable(next);
1980    next.setPreviousExpirable(previous);
1981  }
1982
1983  @GuardedBy("Segment.this")
1984  static <K, V> void nullifyExpirable(ReferenceEntry<K, V> nulled) {
1985    ReferenceEntry<K, V> nullEntry = nullEntry();
1986    nulled.setNextExpirable(nullEntry);
1987    nulled.setPreviousExpirable(nullEntry);
1988  }
1989
1990  // eviction
1991
1992  /**
1993   * Notifies listeners that an entry has been automatically removed due to expiration, eviction,
1994   * or eligibility for garbage collection. This should be called every time expireEntries or
1995   * evictEntry is called (once the lock is released).
1996   */
1997  void processPendingNotifications() {
1998    RemovalNotification<K, V> notification;
1999    while ((notification = removalNotificationQueue.poll()) != null) {
2000      try {
2001        removalListener.onRemoval(notification);
2002      } catch (Exception e) {
2003        logger.log(Level.WARNING, "Exception thrown by removal listener", e);
2004      }
2005    }
2006  }
2007
2008  /** Links the evitables together. */
2009  @GuardedBy("Segment.this")
2010  static <K, V> void connectEvictables(ReferenceEntry<K, V> previous, ReferenceEntry<K, V> next) {
2011    previous.setNextEvictable(next);
2012    next.setPreviousEvictable(previous);
2013  }
2014
2015  @GuardedBy("Segment.this")
2016  static <K, V> void nullifyEvictable(ReferenceEntry<K, V> nulled) {
2017    ReferenceEntry<K, V> nullEntry = nullEntry();
2018    nulled.setNextEvictable(nullEntry);
2019    nulled.setPreviousEvictable(nullEntry);
2020  }
2021
2022  @SuppressWarnings("unchecked")
2023  final Segment<K, V>[] newSegmentArray(int ssize) {
2024    return new Segment[ssize];
2025  }
2026
2027  // Inner Classes
2028
2029  /**
2030   * Segments are specialized versions of hash tables. This subclass inherits from ReentrantLock
2031   * opportunistically, just to simplify some locking and avoid separate construction.
2032   */
2033  @SuppressWarnings("serial") // This class is never serialized.
2034  static class Segment<K, V> extends ReentrantLock {
2035
2036    /*
2037     * TODO(fry): Consider copying variables (like evictsBySize) from outer class into this class.
2038     * It will require more memory but will reduce indirection.
2039     */
2040
2041    /*
2042     * Segments maintain a table of entry lists that are ALWAYS kept in a consistent state, so can
2043     * be read without locking. Next fields of nodes are immutable (final). All list additions are
2044     * performed at the front of each bin. This makes it easy to check changes, and also fast to
2045     * traverse. When nodes would otherwise be changed, new nodes are created to replace them. This
2046     * works well for hash tables since the bin lists tend to be short. (The average length is less
2047     * than two.)
2048     *
2049     * Read operations can thus proceed without locking, but rely on selected uses of volatiles to
2050     * ensure that completed write operations performed by other threads are noticed. For most
2051     * purposes, the "count" field, tracking the number of elements, serves as that volatile
2052     * variable ensuring visibility. This is convenient because this field needs to be read in many
2053     * read operations anyway:
2054     *
2055     * - All (unsynchronized) read operations must first read the "count" field, and should not
2056     * look at table entries if it is 0.
2057     *
2058     * - All (synchronized) write operations should write to the "count" field after structurally
2059     * changing any bin. The operations must not take any action that could even momentarily
2060     * cause a concurrent read operation to see inconsistent data. This is made easier by the
2061     * nature of the read operations in Map. For example, no operation can reveal that the table
2062     * has grown but the threshold has not yet been updated, so there are no atomicity requirements
2063     * for this with respect to reads.
2064     *
2065     * As a guide, all critical volatile reads and writes to the count field are marked in code
2066     * comments.
2067     */
2068
2069    final MapMakerInternalMap<K, V> map;
2070
2071    /**
2072     * The number of live elements in this segment's region. This does not include unset elements
2073     * which are awaiting cleanup.
2074     */
2075    volatile int count;
2076
2077    /**
2078     * Number of updates that alter the size of the table. This is used during bulk-read methods to
2079     * make sure they see a consistent snapshot: If modCounts change during a traversal of segments
2080     * computing size or checking containsValue, then we might have an inconsistent view of state
2081     * so (usually) must retry.
2082     */
2083    int modCount;
2084
2085    /**
2086     * The table is expanded when its size exceeds this threshold. (The value of this field is
2087     * always {@code (int)(capacity * 0.75)}.)
2088     */
2089    int threshold;
2090
2091    /**
2092     * The per-segment table.
2093     */
2094    volatile AtomicReferenceArray<ReferenceEntry<K, V>> table;
2095
2096    /**
2097     * The maximum size of this map. MapMaker.UNSET_INT if there is no maximum.
2098     */
2099    final int maxSegmentSize;
2100
2101    /**
2102     * The key reference queue contains entries whose keys have been garbage collected, and which
2103     * need to be cleaned up internally.
2104     */
2105    final ReferenceQueue<K> keyReferenceQueue;
2106
2107    /**
2108     * The value reference queue contains value references whose values have been garbage collected,
2109     * and which need to be cleaned up internally.
2110     */
2111    final ReferenceQueue<V> valueReferenceQueue;
2112
2113    /**
2114     * The recency queue is used to record which entries were accessed for updating the eviction
2115     * list's ordering. It is drained as a batch operation when either the DRAIN_THRESHOLD is
2116     * crossed or a write occurs on the segment.
2117     */
2118    final Queue<ReferenceEntry<K, V>> recencyQueue;
2119
2120    /**
2121     * A counter of the number of reads since the last write, used to drain queues on a small
2122     * fraction of read operations.
2123     */
2124    final AtomicInteger readCount = new AtomicInteger();
2125
2126    /**
2127     * A queue of elements currently in the map, ordered by access time. Elements are added to the
2128     * tail of the queue on access/write.
2129     */
2130    @GuardedBy("Segment.this")
2131    final Queue<ReferenceEntry<K, V>> evictionQueue;
2132
2133    /**
2134     * A queue of elements currently in the map, ordered by expiration time (either access or write
2135     * time). Elements are added to the tail of the queue on access/write.
2136     */
2137    @GuardedBy("Segment.this")
2138    final Queue<ReferenceEntry<K, V>> expirationQueue;
2139
2140    Segment(MapMakerInternalMap<K, V> map, int initialCapacity, int maxSegmentSize) {
2141      this.map = map;
2142      this.maxSegmentSize = maxSegmentSize;
2143      initTable(newEntryArray(initialCapacity));
2144
2145      keyReferenceQueue = map.usesKeyReferences()
2146           ? new ReferenceQueue<K>() : null;
2147
2148      valueReferenceQueue = map.usesValueReferences()
2149           ? new ReferenceQueue<V>() : null;
2150
2151      recencyQueue = (map.evictsBySize() || map.expiresAfterAccess())
2152          ? new ConcurrentLinkedQueue<ReferenceEntry<K, V>>()
2153          : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
2154
2155      evictionQueue = map.evictsBySize()
2156          ? new EvictionQueue<K, V>()
2157          : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
2158
2159      expirationQueue = map.expires()
2160          ? new ExpirationQueue<K, V>()
2161          : MapMakerInternalMap.<ReferenceEntry<K, V>>discardingQueue();
2162    }
2163
2164    AtomicReferenceArray<ReferenceEntry<K, V>> newEntryArray(int size) {
2165      return new AtomicReferenceArray<ReferenceEntry<K, V>>(size);
2166    }
2167
2168    void initTable(AtomicReferenceArray<ReferenceEntry<K, V>> newTable) {
2169      this.threshold = newTable.length() * 3 / 4; // 0.75
2170      if (this.threshold == maxSegmentSize) {
2171        // prevent spurious expansion before eviction
2172        this.threshold++;
2173      }
2174      this.table = newTable;
2175    }
2176
2177    @GuardedBy("Segment.this")
2178    ReferenceEntry<K, V> newEntry(K key, int hash, @Nullable ReferenceEntry<K, V> next) {
2179      return map.entryFactory.newEntry(this, key, hash, next);
2180    }
2181
2182    @GuardedBy("Segment.this")
2183    ReferenceEntry<K, V> copyEntry(ReferenceEntry<K, V> original, ReferenceEntry<K, V> newNext) {
2184      ValueReference<K, V> valueReference = original.getValueReference();
2185      ReferenceEntry<K, V> newEntry = map.entryFactory.copyEntry(this, original, newNext);
2186      newEntry.setValueReference(valueReference.copyFor(this.valueReferenceQueue, newEntry));
2187      return newEntry;
2188    }
2189
2190    /**
2191     * Sets a new value of an entry. Adds newly created entries at the end of the expiration queue.
2192     */
2193    @GuardedBy("Segment.this")
2194    void setValue(ReferenceEntry<K, V> entry, V value) {
2195      ValueReference<K, V> valueReference = map.valueStrength.referenceValue(this, entry, value);
2196      entry.setValueReference(valueReference);
2197      recordWrite(entry);
2198    }
2199
2200    // reference queues, for garbage collection cleanup
2201
2202    /**
2203     * Cleanup collected entries when the lock is available.
2204     */
2205    void tryDrainReferenceQueues() {
2206      if (tryLock()) {
2207        try {
2208          drainReferenceQueues();
2209        } finally {
2210          unlock();
2211        }
2212      }
2213    }
2214
2215    /**
2216     * Drain the key and value reference queues, cleaning up internal entries containing garbage
2217     * collected keys or values.
2218     */
2219    @GuardedBy("Segment.this")
2220    void drainReferenceQueues() {
2221      if (map.usesKeyReferences()) {
2222        drainKeyReferenceQueue();
2223      }
2224      if (map.usesValueReferences()) {
2225        drainValueReferenceQueue();
2226      }
2227    }
2228
2229    @GuardedBy("Segment.this")
2230    void drainKeyReferenceQueue() {
2231      Reference<? extends K> ref;
2232      int i = 0;
2233      while ((ref = keyReferenceQueue.poll()) != null) {
2234        @SuppressWarnings("unchecked")
2235        ReferenceEntry<K, V> entry = (ReferenceEntry<K, V>) ref;
2236        map.reclaimKey(entry);
2237        if (++i == DRAIN_MAX) {
2238          break;
2239        }
2240      }
2241    }
2242
2243    @GuardedBy("Segment.this")
2244    void drainValueReferenceQueue() {
2245      Reference<? extends V> ref;
2246      int i = 0;
2247      while ((ref = valueReferenceQueue.poll()) != null) {
2248        @SuppressWarnings("unchecked")
2249        ValueReference<K, V> valueReference = (ValueReference<K, V>) ref;
2250        map.reclaimValue(valueReference);
2251        if (++i == DRAIN_MAX) {
2252          break;
2253        }
2254      }
2255    }
2256
2257    /**
2258     * Clears all entries from the key and value reference queues.
2259     */
2260    void clearReferenceQueues() {
2261      if (map.usesKeyReferences()) {
2262        clearKeyReferenceQueue();
2263      }
2264      if (map.usesValueReferences()) {
2265        clearValueReferenceQueue();
2266      }
2267    }
2268
2269    void clearKeyReferenceQueue() {
2270      while (keyReferenceQueue.poll() != null) {}
2271    }
2272
2273    void clearValueReferenceQueue() {
2274      while (valueReferenceQueue.poll() != null) {}
2275    }
2276
2277    // recency queue, shared by expiration and eviction
2278
2279    /**
2280     * Records the relative order in which this read was performed by adding {@code entry} to the
2281     * recency queue. At write-time, or when the queue is full past the threshold, the queue will
2282     * be drained and the entries therein processed.
2283     *
2284     * <p>Note: locked reads should use {@link #recordLockedRead}.
2285     */
2286    void recordRead(ReferenceEntry<K, V> entry) {
2287      if (map.expiresAfterAccess()) {
2288        recordExpirationTime(entry, map.expireAfterAccessNanos);
2289      }
2290      recencyQueue.add(entry);
2291    }
2292
2293    /**
2294     * Updates the eviction metadata that {@code entry} was just read. This currently amounts to
2295     * adding {@code entry} to relevant eviction lists.
2296     *
2297     * <p>Note: this method should only be called under lock, as it directly manipulates the
2298     * eviction queues. Unlocked reads should use {@link #recordRead}.
2299     */
2300    @GuardedBy("Segment.this")
2301    void recordLockedRead(ReferenceEntry<K, V> entry) {
2302      evictionQueue.add(entry);
2303      if (map.expiresAfterAccess()) {
2304        recordExpirationTime(entry, map.expireAfterAccessNanos);
2305        expirationQueue.add(entry);
2306      }
2307    }
2308
2309    /**
2310     * Updates eviction metadata that {@code entry} was just written. This currently amounts to
2311     * adding {@code entry} to relevant eviction lists.
2312     */
2313    @GuardedBy("Segment.this")
2314    void recordWrite(ReferenceEntry<K, V> entry) {
2315      // we are already under lock, so drain the recency queue immediately
2316      drainRecencyQueue();
2317      evictionQueue.add(entry);
2318      if (map.expires()) {
2319        // currently MapMaker ensures that expireAfterWrite and
2320        // expireAfterAccess are mutually exclusive
2321        long expiration = map.expiresAfterAccess()
2322            ? map.expireAfterAccessNanos
2323            : map.expireAfterWriteNanos;
2324        recordExpirationTime(entry, expiration);
2325        expirationQueue.add(entry);
2326      }
2327    }
2328
2329    /**
2330     * Drains the recency queue, updating eviction metadata that the entries therein were read in
2331     * the specified relative order. This currently amounts to adding them to relevant eviction
2332     * lists (accounting for the fact that they could have been removed from the map since being
2333     * added to the recency queue).
2334     */
2335    @GuardedBy("Segment.this")
2336    void drainRecencyQueue() {
2337      ReferenceEntry<K, V> e;
2338      while ((e = recencyQueue.poll()) != null) {
2339        // An entry may be in the recency queue despite it being removed from
2340        // the map . This can occur when the entry was concurrently read while a
2341        // writer is removing it from the segment or after a clear has removed
2342        // all of the segment's entries.
2343        if (evictionQueue.contains(e)) {
2344          evictionQueue.add(e);
2345        }
2346        if (map.expiresAfterAccess() && expirationQueue.contains(e)) {
2347          expirationQueue.add(e);
2348        }
2349      }
2350    }
2351
2352    // expiration
2353
2354    void recordExpirationTime(ReferenceEntry<K, V> entry, long expirationNanos) {
2355      // might overflow, but that's okay (see isExpired())
2356      entry.setExpirationTime(map.ticker.read() + expirationNanos);
2357    }
2358
2359    /**
2360     * Cleanup expired entries when the lock is available.
2361     */
2362    void tryExpireEntries() {
2363      if (tryLock()) {
2364        try {
2365          expireEntries();
2366        } finally {
2367          unlock();
2368          // don't call postWriteCleanup as we're in a read
2369        }
2370      }
2371    }
2372
2373    @GuardedBy("Segment.this")
2374    void expireEntries() {
2375      drainRecencyQueue();
2376
2377      if (expirationQueue.isEmpty()) {
2378        // There's no point in calling nanoTime() if we have no entries to
2379        // expire.
2380        return;
2381      }
2382      long now = map.ticker.read();
2383      ReferenceEntry<K, V> e;
2384      while ((e = expirationQueue.peek()) != null && map.isExpired(e, now)) {
2385        if (!removeEntry(e, e.getHash(), RemovalCause.EXPIRED)) {
2386          throw new AssertionError();
2387        }
2388      }
2389    }
2390
2391    // eviction
2392
2393    void enqueueNotification(ReferenceEntry<K, V> entry, RemovalCause cause) {
2394      enqueueNotification(entry.getKey(), entry.getHash(), entry.getValueReference().get(), cause);
2395    }
2396
2397    void enqueueNotification(@Nullable K key, int hash, @Nullable V value, RemovalCause cause) {
2398      if (map.removalNotificationQueue != DISCARDING_QUEUE) {
2399        RemovalNotification<K, V> notification = new RemovalNotification<K, V>(key, value, cause);
2400        map.removalNotificationQueue.offer(notification);
2401      }
2402    }
2403
2404    /**
2405     * Performs eviction if the segment is full. This should only be called prior to adding a new
2406     * entry and increasing {@code count}.
2407     *
2408     * @return {@code true} if eviction occurred
2409     */
2410    @GuardedBy("Segment.this")
2411    boolean evictEntries() {
2412      if (map.evictsBySize() && count >= maxSegmentSize) {
2413        drainRecencyQueue();
2414
2415        ReferenceEntry<K, V> e = evictionQueue.remove();
2416        if (!removeEntry(e, e.getHash(), RemovalCause.SIZE)) {
2417          throw new AssertionError();
2418        }
2419        return true;
2420      }
2421      return false;
2422    }
2423
2424    /**
2425     * Returns first entry of bin for given hash.
2426     */
2427    ReferenceEntry<K, V> getFirst(int hash) {
2428      // read this volatile field only once
2429      AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2430      return table.get(hash & (table.length() - 1));
2431    }
2432
2433    // Specialized implementations of map methods
2434
2435    ReferenceEntry<K, V> getEntry(Object key, int hash) {
2436      if (count != 0) { // read-volatile
2437        for (ReferenceEntry<K, V> e = getFirst(hash); e != null; e = e.getNext()) {
2438          if (e.getHash() != hash) {
2439            continue;
2440          }
2441
2442          K entryKey = e.getKey();
2443          if (entryKey == null) {
2444            tryDrainReferenceQueues();
2445            continue;
2446          }
2447
2448          if (map.keyEquivalence.equivalent(key, entryKey)) {
2449            return e;
2450          }
2451        }
2452      }
2453
2454      return null;
2455    }
2456
2457    ReferenceEntry<K, V> getLiveEntry(Object key, int hash) {
2458      ReferenceEntry<K, V> e = getEntry(key, hash);
2459      if (e == null) {
2460        return null;
2461      } else if (map.expires() && map.isExpired(e)) {
2462        tryExpireEntries();
2463        return null;
2464      }
2465      return e;
2466    }
2467
2468    V get(Object key, int hash) {
2469      try {
2470        ReferenceEntry<K, V> e = getLiveEntry(key, hash);
2471        if (e == null) {
2472          return null;
2473        }
2474
2475        V value = e.getValueReference().get();
2476        if (value != null) {
2477          recordRead(e);
2478        } else {
2479          tryDrainReferenceQueues();
2480        }
2481        return value;
2482      } finally {
2483        postReadCleanup();
2484      }
2485    }
2486
2487    boolean containsKey(Object key, int hash) {
2488      try {
2489        if (count != 0) { // read-volatile
2490          ReferenceEntry<K, V> e = getLiveEntry(key, hash);
2491          if (e == null) {
2492            return false;
2493          }
2494          return e.getValueReference().get() != null;
2495        }
2496
2497        return false;
2498      } finally {
2499        postReadCleanup();
2500      }
2501    }
2502
2503    /**
2504     * This method is a convenience for testing. Code should call {@link
2505     * MapMakerInternalMap#containsValue} directly.
2506     */
2507    @VisibleForTesting
2508    boolean containsValue(Object value) {
2509      try {
2510        if (count != 0) { // read-volatile
2511          AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2512          int length = table.length();
2513          for (int i = 0; i < length; ++i) {
2514            for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) {
2515              V entryValue = getLiveValue(e);
2516              if (entryValue == null) {
2517                continue;
2518              }
2519              if (map.valueEquivalence.equivalent(value, entryValue)) {
2520                return true;
2521              }
2522            }
2523          }
2524        }
2525
2526        return false;
2527      } finally {
2528        postReadCleanup();
2529      }
2530    }
2531
2532    V put(K key, int hash, V value, boolean onlyIfAbsent) {
2533      lock();
2534      try {
2535        preWriteCleanup();
2536
2537        int newCount = this.count + 1;
2538        if (newCount > this.threshold) { // ensure capacity
2539          expand();
2540          newCount = this.count + 1;
2541        }
2542
2543        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2544        int index = hash & (table.length() - 1);
2545        ReferenceEntry<K, V> first = table.get(index);
2546
2547        // Look for an existing entry.
2548        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2549          K entryKey = e.getKey();
2550          if (e.getHash() == hash && entryKey != null
2551              && map.keyEquivalence.equivalent(key, entryKey)) {
2552            // We found an existing entry.
2553
2554            ValueReference<K, V> valueReference = e.getValueReference();
2555            V entryValue = valueReference.get();
2556
2557            if (entryValue == null) {
2558              ++modCount;
2559              setValue(e, value);
2560              if (!valueReference.isComputingReference()) {
2561                enqueueNotification(key, hash, entryValue, RemovalCause.COLLECTED);
2562                newCount = this.count; // count remains unchanged
2563              } else if (evictEntries()) { // evictEntries after setting new value
2564                newCount = this.count + 1;
2565              }
2566              this.count = newCount; // write-volatile
2567              return null;
2568            } else if (onlyIfAbsent) {
2569              // Mimic
2570              // "if (!map.containsKey(key)) ...
2571              // else return map.get(key);
2572              recordLockedRead(e);
2573              return entryValue;
2574            } else {
2575              // clobber existing entry, count remains unchanged
2576              ++modCount;
2577              enqueueNotification(key, hash, entryValue, RemovalCause.REPLACED);
2578              setValue(e, value);
2579              return entryValue;
2580            }
2581          }
2582        }
2583
2584        // Create a new entry.
2585        ++modCount;
2586        ReferenceEntry<K, V> newEntry = newEntry(key, hash, first);
2587        setValue(newEntry, value);
2588        table.set(index, newEntry);
2589        if (evictEntries()) { // evictEntries after setting new value
2590          newCount = this.count + 1;
2591        }
2592        this.count = newCount; // write-volatile
2593        return null;
2594      } finally {
2595        unlock();
2596        postWriteCleanup();
2597      }
2598    }
2599
2600    /**
2601     * Expands the table if possible.
2602     */
2603    @GuardedBy("Segment.this")
2604    void expand() {
2605      AtomicReferenceArray<ReferenceEntry<K, V>> oldTable = table;
2606      int oldCapacity = oldTable.length();
2607      if (oldCapacity >= MAXIMUM_CAPACITY) {
2608        return;
2609      }
2610
2611      /*
2612       * Reclassify nodes in each list to new Map. Because we are using power-of-two expansion, the
2613       * elements from each bin must either stay at same index, or move with a power of two offset.
2614       * We eliminate unnecessary node creation by catching cases where old nodes can be reused
2615       * because their next fields won't change. Statistically, at the default threshold, only
2616       * about one-sixth of them need cloning when a table doubles. The nodes they replace will be
2617       * garbage collectable as soon as they are no longer referenced by any reader thread that may
2618       * be in the midst of traversing table right now.
2619       */
2620
2621      int newCount = count;
2622      AtomicReferenceArray<ReferenceEntry<K, V>> newTable = newEntryArray(oldCapacity << 1);
2623      threshold = newTable.length() * 3 / 4;
2624      int newMask = newTable.length() - 1;
2625      for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) {
2626        // We need to guarantee that any existing reads of old Map can
2627        // proceed. So we cannot yet null out each bin.
2628        ReferenceEntry<K, V> head = oldTable.get(oldIndex);
2629
2630        if (head != null) {
2631          ReferenceEntry<K, V> next = head.getNext();
2632          int headIndex = head.getHash() & newMask;
2633
2634          // Single node on list
2635          if (next == null) {
2636            newTable.set(headIndex, head);
2637          } else {
2638            // Reuse the consecutive sequence of nodes with the same target
2639            // index from the end of the list. tail points to the first
2640            // entry in the reusable list.
2641            ReferenceEntry<K, V> tail = head;
2642            int tailIndex = headIndex;
2643            for (ReferenceEntry<K, V> e = next; e != null; e = e.getNext()) {
2644              int newIndex = e.getHash() & newMask;
2645              if (newIndex != tailIndex) {
2646                // The index changed. We'll need to copy the previous entry.
2647                tailIndex = newIndex;
2648                tail = e;
2649              }
2650            }
2651            newTable.set(tailIndex, tail);
2652
2653            // Clone nodes leading up to the tail.
2654            for (ReferenceEntry<K, V> e = head; e != tail; e = e.getNext()) {
2655              if (isCollected(e)) {
2656                removeCollectedEntry(e);
2657                newCount--;
2658              } else {
2659                int newIndex = e.getHash() & newMask;
2660                ReferenceEntry<K, V> newNext = newTable.get(newIndex);
2661                ReferenceEntry<K, V> newFirst = copyEntry(e, newNext);
2662                newTable.set(newIndex, newFirst);
2663              }
2664            }
2665          }
2666        }
2667      }
2668      table = newTable;
2669      this.count = newCount;
2670    }
2671
2672    boolean replace(K key, int hash, V oldValue, V newValue) {
2673      lock();
2674      try {
2675        preWriteCleanup();
2676
2677        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2678        int index = hash & (table.length() - 1);
2679        ReferenceEntry<K, V> first = table.get(index);
2680
2681        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2682          K entryKey = e.getKey();
2683          if (e.getHash() == hash && entryKey != null
2684              && map.keyEquivalence.equivalent(key, entryKey)) {
2685            // If the value disappeared, this entry is partially collected,
2686            // and we should pretend like it doesn't exist.
2687            ValueReference<K, V> valueReference = e.getValueReference();
2688            V entryValue = valueReference.get();
2689            if (entryValue == null) {
2690              if (isCollected(valueReference)) {
2691                int newCount = this.count - 1;
2692                ++modCount;
2693                enqueueNotification(entryKey, hash, entryValue, RemovalCause.COLLECTED);
2694                ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
2695                newCount = this.count - 1;
2696                table.set(index, newFirst);
2697                this.count = newCount; // write-volatile
2698              }
2699              return false;
2700            }
2701
2702            if (map.valueEquivalence.equivalent(oldValue, entryValue)) {
2703              ++modCount;
2704              enqueueNotification(key, hash, entryValue, RemovalCause.REPLACED);
2705              setValue(e, newValue);
2706              return true;
2707            } else {
2708              // Mimic
2709              // "if (map.containsKey(key) && map.get(key).equals(oldValue))..."
2710              recordLockedRead(e);
2711              return false;
2712            }
2713          }
2714        }
2715
2716        return false;
2717      } finally {
2718        unlock();
2719        postWriteCleanup();
2720      }
2721    }
2722
2723    V replace(K key, int hash, V newValue) {
2724      lock();
2725      try {
2726        preWriteCleanup();
2727
2728        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2729        int index = hash & (table.length() - 1);
2730        ReferenceEntry<K, V> first = table.get(index);
2731
2732        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2733          K entryKey = e.getKey();
2734          if (e.getHash() == hash && entryKey != null
2735              && map.keyEquivalence.equivalent(key, entryKey)) {
2736            // If the value disappeared, this entry is partially collected,
2737            // and we should pretend like it doesn't exist.
2738            ValueReference<K, V> valueReference = e.getValueReference();
2739            V entryValue = valueReference.get();
2740            if (entryValue == null) {
2741              if (isCollected(valueReference)) {
2742                int newCount = this.count - 1;
2743                ++modCount;
2744                enqueueNotification(entryKey, hash, entryValue, RemovalCause.COLLECTED);
2745                ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
2746                newCount = this.count - 1;
2747                table.set(index, newFirst);
2748                this.count = newCount; // write-volatile
2749              }
2750              return null;
2751            }
2752
2753            ++modCount;
2754            enqueueNotification(key, hash, entryValue, RemovalCause.REPLACED);
2755            setValue(e, newValue);
2756            return entryValue;
2757          }
2758        }
2759
2760        return null;
2761      } finally {
2762        unlock();
2763        postWriteCleanup();
2764      }
2765    }
2766
2767    V remove(Object key, int hash) {
2768      lock();
2769      try {
2770        preWriteCleanup();
2771
2772        int newCount = this.count - 1;
2773        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2774        int index = hash & (table.length() - 1);
2775        ReferenceEntry<K, V> first = table.get(index);
2776
2777        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2778          K entryKey = e.getKey();
2779          if (e.getHash() == hash && entryKey != null
2780              && map.keyEquivalence.equivalent(key, entryKey)) {
2781            ValueReference<K, V> valueReference = e.getValueReference();
2782            V entryValue = valueReference.get();
2783
2784            RemovalCause cause;
2785            if (entryValue != null) {
2786              cause = RemovalCause.EXPLICIT;
2787            } else if (isCollected(valueReference)) {
2788              cause = RemovalCause.COLLECTED;
2789            } else {
2790              return null;
2791            }
2792
2793            ++modCount;
2794            enqueueNotification(entryKey, hash, entryValue, cause);
2795            ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
2796            newCount = this.count - 1;
2797            table.set(index, newFirst);
2798            this.count = newCount; // write-volatile
2799            return entryValue;
2800          }
2801        }
2802
2803        return null;
2804      } finally {
2805        unlock();
2806        postWriteCleanup();
2807      }
2808    }
2809
2810    boolean remove(Object key, int hash, Object value) {
2811      lock();
2812      try {
2813        preWriteCleanup();
2814
2815        int newCount = this.count - 1;
2816        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2817        int index = hash & (table.length() - 1);
2818        ReferenceEntry<K, V> first = table.get(index);
2819
2820        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2821          K entryKey = e.getKey();
2822          if (e.getHash() == hash && entryKey != null
2823              && map.keyEquivalence.equivalent(key, entryKey)) {
2824            ValueReference<K, V> valueReference = e.getValueReference();
2825            V entryValue = valueReference.get();
2826
2827            RemovalCause cause;
2828            if (map.valueEquivalence.equivalent(value, entryValue)) {
2829              cause = RemovalCause.EXPLICIT;
2830            } else if (isCollected(valueReference)) {
2831              cause = RemovalCause.COLLECTED;
2832            } else {
2833              return false;
2834            }
2835
2836            ++modCount;
2837            enqueueNotification(entryKey, hash, entryValue, cause);
2838            ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
2839            newCount = this.count - 1;
2840            table.set(index, newFirst);
2841            this.count = newCount; // write-volatile
2842            return (cause == RemovalCause.EXPLICIT);
2843          }
2844        }
2845
2846        return false;
2847      } finally {
2848        unlock();
2849        postWriteCleanup();
2850      }
2851    }
2852
2853    void clear() {
2854      if (count != 0) {
2855        lock();
2856        try {
2857          AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2858          if (map.removalNotificationQueue != DISCARDING_QUEUE) {
2859            for (int i = 0; i < table.length(); ++i) {
2860              for (ReferenceEntry<K, V> e = table.get(i); e != null; e = e.getNext()) {
2861                // Computing references aren't actually in the map yet.
2862                if (!e.getValueReference().isComputingReference()) {
2863                  enqueueNotification(e, RemovalCause.EXPLICIT);
2864                }
2865              }
2866            }
2867          }
2868          for (int i = 0; i < table.length(); ++i) {
2869            table.set(i, null);
2870          }
2871          clearReferenceQueues();
2872          evictionQueue.clear();
2873          expirationQueue.clear();
2874          readCount.set(0);
2875
2876          ++modCount;
2877          count = 0; // write-volatile
2878        } finally {
2879          unlock();
2880          postWriteCleanup();
2881        }
2882      }
2883    }
2884
2885    /**
2886     * Removes an entry from within a table. All entries following the removed node can stay, but
2887     * all preceding ones need to be cloned.
2888     *
2889     * <p>This method does not decrement count for the removed entry, but does decrement count for
2890     * all partially collected entries which are skipped. As such callers which are modifying count
2891     * must re-read it after calling removeFromChain.
2892     *
2893     * @param first the first entry of the table
2894     * @param entry the entry being removed from the table
2895     * @return the new first entry for the table
2896     */
2897    @GuardedBy("Segment.this")
2898    ReferenceEntry<K, V> removeFromChain(ReferenceEntry<K, V> first, ReferenceEntry<K, V> entry) {
2899      evictionQueue.remove(entry);
2900      expirationQueue.remove(entry);
2901
2902      int newCount = count;
2903      ReferenceEntry<K, V> newFirst = entry.getNext();
2904      for (ReferenceEntry<K, V> e = first; e != entry; e = e.getNext()) {
2905        if (isCollected(e)) {
2906          removeCollectedEntry(e);
2907          newCount--;
2908        } else {
2909          newFirst = copyEntry(e, newFirst);
2910        }
2911      }
2912      this.count = newCount;
2913      return newFirst;
2914    }
2915
2916    void removeCollectedEntry(ReferenceEntry<K, V> entry) {
2917      enqueueNotification(entry, RemovalCause.COLLECTED);
2918      evictionQueue.remove(entry);
2919      expirationQueue.remove(entry);
2920    }
2921
2922    /**
2923     * Removes an entry whose key has been garbage collected.
2924     */
2925    boolean reclaimKey(ReferenceEntry<K, V> entry, int hash) {
2926      lock();
2927      try {
2928        int newCount = count - 1;
2929        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2930        int index = hash & (table.length() - 1);
2931        ReferenceEntry<K, V> first = table.get(index);
2932
2933        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2934          if (e == entry) {
2935            ++modCount;
2936            enqueueNotification(
2937                e.getKey(), hash, e.getValueReference().get(), RemovalCause.COLLECTED);
2938            ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
2939            newCount = this.count - 1;
2940            table.set(index, newFirst);
2941            this.count = newCount; // write-volatile
2942            return true;
2943          }
2944        }
2945
2946        return false;
2947      } finally {
2948        unlock();
2949        postWriteCleanup();
2950      }
2951    }
2952
2953    /**
2954     * Removes an entry whose value has been garbage collected.
2955     */
2956    boolean reclaimValue(K key, int hash, ValueReference<K, V> valueReference) {
2957      lock();
2958      try {
2959        int newCount = this.count - 1;
2960        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2961        int index = hash & (table.length() - 1);
2962        ReferenceEntry<K, V> first = table.get(index);
2963
2964        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
2965          K entryKey = e.getKey();
2966          if (e.getHash() == hash && entryKey != null
2967              && map.keyEquivalence.equivalent(key, entryKey)) {
2968            ValueReference<K, V> v = e.getValueReference();
2969            if (v == valueReference) {
2970              ++modCount;
2971              enqueueNotification(key, hash, valueReference.get(), RemovalCause.COLLECTED);
2972              ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
2973              newCount = this.count - 1;
2974              table.set(index, newFirst);
2975              this.count = newCount; // write-volatile
2976              return true;
2977            }
2978            return false;
2979          }
2980        }
2981
2982        return false;
2983      } finally {
2984        unlock();
2985        if (!isHeldByCurrentThread()) { // don't cleanup inside of put
2986          postWriteCleanup();
2987        }
2988      }
2989    }
2990
2991    /**
2992     * Clears a value that has not yet been set, and thus does not require count to be modified.
2993     */
2994    boolean clearValue(K key, int hash, ValueReference<K, V> valueReference) {
2995      lock();
2996      try {
2997        AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
2998        int index = hash & (table.length() - 1);
2999        ReferenceEntry<K, V> first = table.get(index);
3000
3001        for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
3002          K entryKey = e.getKey();
3003          if (e.getHash() == hash && entryKey != null
3004              && map.keyEquivalence.equivalent(key, entryKey)) {
3005            ValueReference<K, V> v = e.getValueReference();
3006            if (v == valueReference) {
3007              ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
3008              table.set(index, newFirst);
3009              return true;
3010            }
3011            return false;
3012          }
3013        }
3014
3015        return false;
3016      } finally {
3017        unlock();
3018        postWriteCleanup();
3019      }
3020    }
3021
3022    @GuardedBy("Segment.this")
3023    boolean removeEntry(ReferenceEntry<K, V> entry, int hash, RemovalCause cause) {
3024      int newCount = this.count - 1;
3025      AtomicReferenceArray<ReferenceEntry<K, V>> table = this.table;
3026      int index = hash & (table.length() - 1);
3027      ReferenceEntry<K, V> first = table.get(index);
3028
3029      for (ReferenceEntry<K, V> e = first; e != null; e = e.getNext()) {
3030        if (e == entry) {
3031          ++modCount;
3032          enqueueNotification(e.getKey(), hash, e.getValueReference().get(), cause);
3033          ReferenceEntry<K, V> newFirst = removeFromChain(first, e);
3034          newCount = this.count - 1;
3035          table.set(index, newFirst);
3036          this.count = newCount; // write-volatile
3037          return true;
3038        }
3039      }
3040
3041      return false;
3042    }
3043
3044    /**
3045     * Returns {@code true} if the entry has been partially collected, meaning that either the key
3046     * is null, or the value is null and it is not computing.
3047     */
3048    boolean isCollected(ReferenceEntry<K, V> entry) {
3049      if (entry.getKey() == null) {
3050        return true;
3051      }
3052      return isCollected(entry.getValueReference());
3053    }
3054
3055    /**
3056     * Returns {@code true} if the value has been partially collected, meaning that the value is
3057     * null and it is not computing.
3058     */
3059    boolean isCollected(ValueReference<K, V> valueReference) {
3060      if (valueReference.isComputingReference()) {
3061        return false;
3062      }
3063      return (valueReference.get() == null);
3064    }
3065
3066    /**
3067     * Gets the value from an entry. Returns {@code null} if the entry is invalid,
3068     * partially-collected, computing, or expired.
3069     */
3070    V getLiveValue(ReferenceEntry<K, V> entry) {
3071      if (entry.getKey() == null) {
3072        tryDrainReferenceQueues();
3073        return null;
3074      }
3075      V value = entry.getValueReference().get();
3076      if (value == null) {
3077        tryDrainReferenceQueues();
3078        return null;
3079      }
3080
3081      if (map.expires() && map.isExpired(entry)) {
3082        tryExpireEntries();
3083        return null;
3084      }
3085      return value;
3086    }
3087
3088    /**
3089     * Performs routine cleanup following a read. Normally cleanup happens during writes, or from
3090     * the cleanupExecutor. If cleanup is not observed after a sufficient number of reads, try
3091     * cleaning up from the read thread.
3092     */
3093    void postReadCleanup() {
3094      if ((readCount.incrementAndGet() & DRAIN_THRESHOLD) == 0) {
3095        runCleanup();
3096      }
3097    }
3098
3099    /**
3100     * Performs routine cleanup prior to executing a write. This should be called every time a
3101     * write thread acquires the segment lock, immediately after acquiring the lock.
3102     *
3103     * <p>Post-condition: expireEntries has been run.
3104     */
3105    @GuardedBy("Segment.this")
3106    void preWriteCleanup() {
3107      runLockedCleanup();
3108    }
3109
3110    /**
3111     * Performs routine cleanup following a write.
3112     */
3113    void postWriteCleanup() {
3114      runUnlockedCleanup();
3115    }
3116
3117    void runCleanup() {
3118      runLockedCleanup();
3119      runUnlockedCleanup();
3120    }
3121
3122    void runLockedCleanup() {
3123      if (tryLock()) {
3124        try {
3125          drainReferenceQueues();
3126          expireEntries(); // calls drainRecencyQueue
3127          readCount.set(0);
3128        } finally {
3129          unlock();
3130        }
3131      }
3132    }
3133
3134    void runUnlockedCleanup() {
3135      // locked cleanup may generate notifications we can send unlocked
3136      if (!isHeldByCurrentThread()) {
3137        map.processPendingNotifications();
3138      }
3139    }
3140
3141  }
3142
3143  // Queues
3144
3145  /**
3146   * A custom queue for managing eviction order. Note that this is tightly integrated with {@code
3147   * ReferenceEntry}, upon which it relies to perform its linking.
3148   *
3149   * <p>Note that this entire implementation makes the assumption that all elements which are in
3150   * the map are also in this queue, and that all elements not in the queue are not in the map.
3151   *
3152   * <p>The benefits of creating our own queue are that (1) we can replace elements in the middle
3153   * of the queue as part of copyEvictableEntry, and (2) the contains method is highly optimized
3154   * for the current model.
3155   */
3156  static final class EvictionQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
3157    final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
3158
3159      ReferenceEntry<K, V> nextEvictable = this;
3160
3161      @Override
3162      public ReferenceEntry<K, V> getNextEvictable() {
3163        return nextEvictable;
3164      }
3165
3166      @Override
3167      public void setNextEvictable(ReferenceEntry<K, V> next) {
3168        this.nextEvictable = next;
3169      }
3170
3171      ReferenceEntry<K, V> previousEvictable = this;
3172
3173      @Override
3174      public ReferenceEntry<K, V> getPreviousEvictable() {
3175        return previousEvictable;
3176      }
3177
3178      @Override
3179      public void setPreviousEvictable(ReferenceEntry<K, V> previous) {
3180        this.previousEvictable = previous;
3181      }
3182    };
3183
3184    // implements Queue
3185
3186    @Override
3187    public boolean offer(ReferenceEntry<K, V> entry) {
3188      // unlink
3189      connectEvictables(entry.getPreviousEvictable(), entry.getNextEvictable());
3190
3191      // add to tail
3192      connectEvictables(head.getPreviousEvictable(), entry);
3193      connectEvictables(entry, head);
3194
3195      return true;
3196    }
3197
3198    @Override
3199    public ReferenceEntry<K, V> peek() {
3200      ReferenceEntry<K, V> next = head.getNextEvictable();
3201      return (next == head) ? null : next;
3202    }
3203
3204    @Override
3205    public ReferenceEntry<K, V> poll() {
3206      ReferenceEntry<K, V> next = head.getNextEvictable();
3207      if (next == head) {
3208        return null;
3209      }
3210
3211      remove(next);
3212      return next;
3213    }
3214
3215    @Override
3216    @SuppressWarnings("unchecked")
3217    public boolean remove(Object o) {
3218      ReferenceEntry<K, V> e = (ReferenceEntry) o;
3219      ReferenceEntry<K, V> previous = e.getPreviousEvictable();
3220      ReferenceEntry<K, V> next = e.getNextEvictable();
3221      connectEvictables(previous, next);
3222      nullifyEvictable(e);
3223
3224      return next != NullEntry.INSTANCE;
3225    }
3226
3227    @Override
3228    @SuppressWarnings("unchecked")
3229    public boolean contains(Object o) {
3230      ReferenceEntry<K, V> e = (ReferenceEntry) o;
3231      return e.getNextEvictable() != NullEntry.INSTANCE;
3232    }
3233
3234    @Override
3235    public boolean isEmpty() {
3236      return head.getNextEvictable() == head;
3237    }
3238
3239    @Override
3240    public int size() {
3241      int size = 0;
3242      for (ReferenceEntry<K, V> e = head.getNextEvictable(); e != head; e = e.getNextEvictable()) {
3243        size++;
3244      }
3245      return size;
3246    }
3247
3248    @Override
3249    public void clear() {
3250      ReferenceEntry<K, V> e = head.getNextEvictable();
3251      while (e != head) {
3252        ReferenceEntry<K, V> next = e.getNextEvictable();
3253        nullifyEvictable(e);
3254        e = next;
3255      }
3256
3257      head.setNextEvictable(head);
3258      head.setPreviousEvictable(head);
3259    }
3260
3261    @Override
3262    public Iterator<ReferenceEntry<K, V>> iterator() {
3263      return new AbstractLinkedIterator<ReferenceEntry<K, V>>(peek()) {
3264        @Override
3265        protected ReferenceEntry<K, V> computeNext(ReferenceEntry<K, V> previous) {
3266          ReferenceEntry<K, V> next = previous.getNextEvictable();
3267          return (next == head) ? null : next;
3268        }
3269      };
3270    }
3271  }
3272
3273  /**
3274   * A custom queue for managing expiration order. Note that this is tightly integrated with
3275   * {@code ReferenceEntry}, upon which it reliese to perform its linking.
3276   *
3277   * <p>Note that this entire implementation makes the assumption that all elements which are in
3278   * the map are also in this queue, and that all elements not in the queue are not in the map.
3279   *
3280   * <p>The benefits of creating our own queue are that (1) we can replace elements in the middle
3281   * of the queue as part of copyEvictableEntry, and (2) the contains method is highly optimized
3282   * for the current model.
3283   */
3284  static final class ExpirationQueue<K, V> extends AbstractQueue<ReferenceEntry<K, V>> {
3285    final ReferenceEntry<K, V> head = new AbstractReferenceEntry<K, V>() {
3286
3287      @Override
3288      public long getExpirationTime() {
3289        return Long.MAX_VALUE;
3290      }
3291
3292      @Override
3293      public void setExpirationTime(long time) {}
3294
3295      ReferenceEntry<K, V> nextExpirable = this;
3296
3297      @Override
3298      public ReferenceEntry<K, V> getNextExpirable() {
3299        return nextExpirable;
3300      }
3301
3302      @Override
3303      public void setNextExpirable(ReferenceEntry<K, V> next) {
3304        this.nextExpirable = next;
3305      }
3306
3307      ReferenceEntry<K, V> previousExpirable = this;
3308
3309      @Override
3310      public ReferenceEntry<K, V> getPreviousExpirable() {
3311        return previousExpirable;
3312      }
3313
3314      @Override
3315      public void setPreviousExpirable(ReferenceEntry<K, V> previous) {
3316        this.previousExpirable = previous;
3317      }
3318    };
3319
3320    // implements Queue
3321
3322    @Override
3323    public boolean offer(ReferenceEntry<K, V> entry) {
3324      // unlink
3325      connectExpirables(entry.getPreviousExpirable(), entry.getNextExpirable());
3326
3327      // add to tail
3328      connectExpirables(head.getPreviousExpirable(), entry);
3329      connectExpirables(entry, head);
3330
3331      return true;
3332    }
3333
3334    @Override
3335    public ReferenceEntry<K, V> peek() {
3336      ReferenceEntry<K, V> next = head.getNextExpirable();
3337      return (next == head) ? null : next;
3338    }
3339
3340    @Override
3341    public ReferenceEntry<K, V> poll() {
3342      ReferenceEntry<K, V> next = head.getNextExpirable();
3343      if (next == head) {
3344        return null;
3345      }
3346
3347      remove(next);
3348      return next;
3349    }
3350
3351    @Override
3352    @SuppressWarnings("unchecked")
3353    public boolean remove(Object o) {
3354      ReferenceEntry<K, V> e = (ReferenceEntry) o;
3355      ReferenceEntry<K, V> previous = e.getPreviousExpirable();
3356      ReferenceEntry<K, V> next = e.getNextExpirable();
3357      connectExpirables(previous, next);
3358      nullifyExpirable(e);
3359
3360      return next != NullEntry.INSTANCE;
3361    }
3362
3363    @Override
3364    @SuppressWarnings("unchecked")
3365    public boolean contains(Object o) {
3366      ReferenceEntry<K, V> e = (ReferenceEntry) o;
3367      return e.getNextExpirable() != NullEntry.INSTANCE;
3368    }
3369
3370    @Override
3371    public boolean isEmpty() {
3372      return head.getNextExpirable() == head;
3373    }
3374
3375    @Override
3376    public int size() {
3377      int size = 0;
3378      for (ReferenceEntry<K, V> e = head.getNextExpirable(); e != head; e = e.getNextExpirable()) {
3379        size++;
3380      }
3381      return size;
3382    }
3383
3384    @Override
3385    public void clear() {
3386      ReferenceEntry<K, V> e = head.getNextExpirable();
3387      while (e != head) {
3388        ReferenceEntry<K, V> next = e.getNextExpirable();
3389        nullifyExpirable(e);
3390        e = next;
3391      }
3392
3393      head.setNextExpirable(head);
3394      head.setPreviousExpirable(head);
3395    }
3396
3397    @Override
3398    public Iterator<ReferenceEntry<K, V>> iterator() {
3399      return new AbstractLinkedIterator<ReferenceEntry<K, V>>(peek()) {
3400        @Override
3401        protected ReferenceEntry<K, V> computeNext(ReferenceEntry<K, V> previous) {
3402          ReferenceEntry<K, V> next = previous.getNextExpirable();
3403          return (next == head) ? null : next;
3404        }
3405      };
3406    }
3407  }
3408
3409  static final class CleanupMapTask implements Runnable {
3410    final WeakReference<MapMakerInternalMap<?, ?>> mapReference;
3411
3412    public CleanupMapTask(MapMakerInternalMap<?, ?> map) {
3413      this.mapReference = new WeakReference<MapMakerInternalMap<?, ?>>(map);
3414    }
3415
3416    @Override
3417    public void run() {
3418      MapMakerInternalMap<?, ?> map = mapReference.get();
3419      if (map == null) {
3420        throw new CancellationException();
3421      }
3422
3423      for (Segment<?, ?> segment : map.segments) {
3424        segment.runCleanup();
3425      }
3426    }
3427  }
3428
3429  // ConcurrentMap methods
3430
3431  @Override
3432  public boolean isEmpty() {
3433    /*
3434     * Sum per-segment modCounts to avoid mis-reporting when elements are concurrently added and
3435     * removed in one segment while checking another, in which case the table was never actually
3436     * empty at any point. (The sum ensures accuracy up through at least 1<<31 per-segment
3437     * modifications before recheck.)  Method containsValue() uses similar constructions for
3438     * stability checks.
3439     */
3440    long sum = 0L;
3441    Segment<K, V>[] segments = this.segments;
3442    for (int i = 0; i < segments.length; ++i) {
3443      if (segments[i].count != 0) {
3444        return false;
3445      }
3446      sum += segments[i].modCount;
3447    }
3448
3449    if (sum != 0L) { // recheck unless no modifications
3450      for (int i = 0; i < segments.length; ++i) {
3451        if (segments[i].count != 0) {
3452          return false;
3453        }
3454        sum -= segments[i].modCount;
3455      }
3456      if (sum != 0L) {
3457        return false;
3458      }
3459    }
3460    return true;
3461  }
3462
3463  @Override
3464  public int size() {
3465    Segment<K, V>[] segments = this.segments;
3466    long sum = 0;
3467    for (int i = 0; i < segments.length; ++i) {
3468      sum += segments[i].count;
3469    }
3470    return Ints.saturatedCast(sum);
3471  }
3472
3473  @Override
3474  public V get(@Nullable Object key) {
3475    if (key == null) {
3476      return null;
3477    }
3478    int hash = hash(key);
3479    return segmentFor(hash).get(key, hash);
3480  }
3481
3482  /**
3483   * Returns the internal entry for the specified key. The entry may be computing, expired, or
3484   * partially collected. Does not impact recency ordering.
3485   */
3486  ReferenceEntry<K, V> getEntry(@Nullable Object key) {
3487    if (key == null) {
3488      return null;
3489    }
3490    int hash = hash(key);
3491    return segmentFor(hash).getEntry(key, hash);
3492  }
3493
3494  /**
3495   * Returns the live internal entry for the specified key. Does not impact recency ordering.
3496   */
3497  ReferenceEntry<K, V> getLiveEntry(@Nullable Object key) {
3498    if (key == null) {
3499      return null;
3500    }
3501    int hash = hash(key);
3502    return segmentFor(hash).getLiveEntry(key, hash);
3503  }
3504
3505  @Override
3506  public boolean containsKey(@Nullable Object key) {
3507    if (key == null) {
3508      return false;
3509    }
3510    int hash = hash(key);
3511    return segmentFor(hash).containsKey(key, hash);
3512  }
3513
3514  @Override
3515  public boolean containsValue(@Nullable Object value) {
3516    if (value == null) {
3517      return false;
3518    }
3519
3520    // This implementation is patterned after ConcurrentHashMap, but without the locking. The only
3521    // way for it to return a false negative would be for the target value to jump around in the map
3522    // such that none of the subsequent iterations observed it, despite the fact that at every point
3523    // in time it was present somewhere int the map. This becomes increasingly unlikely as
3524    // CONTAINS_VALUE_RETRIES increases, though without locking it is theoretically possible.
3525    final Segment<K,V>[] segments = this.segments;
3526    long last = -1L;
3527    for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) {
3528      long sum = 0L;
3529      for (Segment<K, V> segment : segments) {
3530        // ensure visibility of most recent completed write
3531        @SuppressWarnings({"UnusedDeclaration", "unused"})
3532        int c = segment.count; // read-volatile
3533
3534        AtomicReferenceArray<ReferenceEntry<K, V>> table = segment.table;
3535        for (int j = 0 ; j < table.length(); j++) {
3536          for (ReferenceEntry<K, V> e = table.get(j); e != null; e = e.getNext()) {
3537            V v = segment.getLiveValue(e);
3538            if (v != null && valueEquivalence.equivalent(value, v)) {
3539              return true;
3540            }
3541          }
3542        }
3543        sum += segment.modCount;
3544      }
3545      if (sum == last) {
3546        break;
3547      }
3548      last = sum;
3549    }
3550    return false;
3551  }
3552
3553  @Override
3554  public V put(K key, V value) {
3555    checkNotNull(key);
3556    checkNotNull(value);
3557    int hash = hash(key);
3558    return segmentFor(hash).put(key, hash, value, false);
3559  }
3560
3561  @Override
3562  public V putIfAbsent(K key, V value) {
3563    checkNotNull(key);
3564    checkNotNull(value);
3565    int hash = hash(key);
3566    return segmentFor(hash).put(key, hash, value, true);
3567  }
3568
3569  @Override
3570  public void putAll(Map<? extends K, ? extends V> m) {
3571    for (Entry<? extends K, ? extends V> e : m.entrySet()) {
3572      put(e.getKey(), e.getValue());
3573    }
3574  }
3575
3576  @Override
3577  public V remove(@Nullable Object key) {
3578    if (key == null) {
3579      return null;
3580    }
3581    int hash = hash(key);
3582    return segmentFor(hash).remove(key, hash);
3583  }
3584
3585  @Override
3586  public boolean remove(@Nullable Object key, @Nullable Object value) {
3587    if (key == null || value == null) {
3588      return false;
3589    }
3590    int hash = hash(key);
3591    return segmentFor(hash).remove(key, hash, value);
3592  }
3593
3594  @Override
3595  public boolean replace(K key, @Nullable V oldValue, V newValue) {
3596    checkNotNull(key);
3597    checkNotNull(newValue);
3598    if (oldValue == null) {
3599      return false;
3600    }
3601    int hash = hash(key);
3602    return segmentFor(hash).replace(key, hash, oldValue, newValue);
3603  }
3604
3605  @Override
3606  public V replace(K key, V value) {
3607    checkNotNull(key);
3608    checkNotNull(value);
3609    int hash = hash(key);
3610    return segmentFor(hash).replace(key, hash, value);
3611  }
3612
3613  @Override
3614  public void clear() {
3615    for (Segment<K, V> segment : segments) {
3616      segment.clear();
3617    }
3618  }
3619
3620  Set<K> keySet;
3621
3622  @Override
3623  public Set<K> keySet() {
3624    Set<K> ks = keySet;
3625    return (ks != null) ? ks : (keySet = new KeySet());
3626  }
3627
3628  Collection<V> values;
3629
3630  @Override
3631  public Collection<V> values() {
3632    Collection<V> vs = values;
3633    return (vs != null) ? vs : (values = new Values());
3634  }
3635
3636  Set<Entry<K, V>> entrySet;
3637
3638  @Override
3639  public Set<Entry<K, V>> entrySet() {
3640    Set<Entry<K, V>> es = entrySet;
3641    return (es != null) ? es : (entrySet = new EntrySet());
3642  }
3643
3644  // Iterator Support
3645
3646  abstract class HashIterator {
3647
3648    int nextSegmentIndex;
3649    int nextTableIndex;
3650    Segment<K, V> currentSegment;
3651    AtomicReferenceArray<ReferenceEntry<K, V>> currentTable;
3652    ReferenceEntry<K, V> nextEntry;
3653    WriteThroughEntry nextExternal;
3654    WriteThroughEntry lastReturned;
3655
3656    HashIterator() {
3657      nextSegmentIndex = segments.length - 1;
3658      nextTableIndex = -1;
3659      advance();
3660    }
3661
3662    final void advance() {
3663      nextExternal = null;
3664
3665      if (nextInChain()) {
3666        return;
3667      }
3668
3669      if (nextInTable()) {
3670        return;
3671      }
3672
3673      while (nextSegmentIndex >= 0) {
3674        currentSegment = segments[nextSegmentIndex--];
3675        if (currentSegment.count != 0) {
3676          currentTable = currentSegment.table;
3677          nextTableIndex = currentTable.length() - 1;
3678          if (nextInTable()) {
3679            return;
3680          }
3681        }
3682      }
3683    }
3684
3685    /**
3686     * Finds the next entry in the current chain. Returns {@code true} if an entry was found.
3687     */
3688    boolean nextInChain() {
3689      if (nextEntry != null) {
3690        for (nextEntry = nextEntry.getNext(); nextEntry != null; nextEntry = nextEntry.getNext()) {
3691          if (advanceTo(nextEntry)) {
3692            return true;
3693          }
3694        }
3695      }
3696      return false;
3697    }
3698
3699    /**
3700     * Finds the next entry in the current table. Returns {@code true} if an entry was found.
3701     */
3702    boolean nextInTable() {
3703      while (nextTableIndex >= 0) {
3704        if ((nextEntry = currentTable.get(nextTableIndex--)) != null) {
3705          if (advanceTo(nextEntry) || nextInChain()) {
3706            return true;
3707          }
3708        }
3709      }
3710      return false;
3711    }
3712
3713    /**
3714     * Advances to the given entry. Returns {@code true} if the entry was valid, {@code false} if it
3715     * should be skipped.
3716     */
3717    boolean advanceTo(ReferenceEntry<K, V> entry) {
3718      try {
3719        K key = entry.getKey();
3720        V value = getLiveValue(entry);
3721        if (value != null) {
3722          nextExternal = new WriteThroughEntry(key, value);
3723          return true;
3724        } else {
3725          // Skip stale entry.
3726          return false;
3727        }
3728      } finally {
3729        currentSegment.postReadCleanup();
3730      }
3731    }
3732
3733    public boolean hasNext() {
3734      return nextExternal != null;
3735    }
3736
3737    WriteThroughEntry nextEntry() {
3738      if (nextExternal == null) {
3739        throw new NoSuchElementException();
3740      }
3741      lastReturned = nextExternal;
3742      advance();
3743      return lastReturned;
3744    }
3745
3746    public void remove() {
3747      checkState(lastReturned != null);
3748      MapMakerInternalMap.this.remove(lastReturned.getKey());
3749      lastReturned = null;
3750    }
3751  }
3752
3753  final class KeyIterator extends HashIterator implements Iterator<K> {
3754
3755    @Override
3756    public K next() {
3757      return nextEntry().getKey();
3758    }
3759  }
3760
3761  final class ValueIterator extends HashIterator implements Iterator<V> {
3762
3763    @Override
3764    public V next() {
3765      return nextEntry().getValue();
3766    }
3767  }
3768
3769  /**
3770   * Custom Entry class used by EntryIterator.next(), that relays setValue changes to the
3771   * underlying map.
3772   */
3773  final class WriteThroughEntry extends AbstractMapEntry<K, V> {
3774    final K key; // non-null
3775    V value; // non-null
3776
3777    WriteThroughEntry(K key, V value) {
3778      this.key = key;
3779      this.value = value;
3780    }
3781
3782    @Override
3783    public K getKey() {
3784      return key;
3785    }
3786
3787    @Override
3788    public V getValue() {
3789      return value;
3790    }
3791
3792    @Override
3793    public boolean equals(@Nullable Object object) {
3794      // Cannot use key and value equivalence
3795      if (object instanceof Entry) {
3796        Entry<?, ?> that = (Entry<?, ?>) object;
3797        return key.equals(that.getKey()) && value.equals(that.getValue());
3798      }
3799      return false;
3800    }
3801
3802    @Override
3803    public int hashCode() {
3804      // Cannot use key and value equivalence
3805      return key.hashCode() ^ value.hashCode();
3806    }
3807
3808    @Override
3809    public V setValue(V newValue) {
3810      V oldValue = put(key, newValue);
3811      value = newValue; // only if put succeeds
3812      return oldValue;
3813    }
3814  }
3815
3816  final class EntryIterator extends HashIterator implements Iterator<Entry<K, V>> {
3817
3818    @Override
3819    public Entry<K, V> next() {
3820      return nextEntry();
3821    }
3822  }
3823
3824  final class KeySet extends AbstractSet<K> {
3825
3826    @Override
3827    public Iterator<K> iterator() {
3828      return new KeyIterator();
3829    }
3830
3831    @Override
3832    public int size() {
3833      return MapMakerInternalMap.this.size();
3834    }
3835
3836    @Override
3837    public boolean isEmpty() {
3838      return MapMakerInternalMap.this.isEmpty();
3839    }
3840
3841    @Override
3842    public boolean contains(Object o) {
3843      return MapMakerInternalMap.this.containsKey(o);
3844    }
3845
3846    @Override
3847    public boolean remove(Object o) {
3848      return MapMakerInternalMap.this.remove(o) != null;
3849    }
3850
3851    @Override
3852    public void clear() {
3853      MapMakerInternalMap.this.clear();
3854    }
3855  }
3856
3857  final class Values extends AbstractCollection<V> {
3858
3859    @Override
3860    public Iterator<V> iterator() {
3861      return new ValueIterator();
3862    }
3863
3864    @Override
3865    public int size() {
3866      return MapMakerInternalMap.this.size();
3867    }
3868
3869    @Override
3870    public boolean isEmpty() {
3871      return MapMakerInternalMap.this.isEmpty();
3872    }
3873
3874    @Override
3875    public boolean contains(Object o) {
3876      return MapMakerInternalMap.this.containsValue(o);
3877    }
3878
3879    @Override
3880    public void clear() {
3881      MapMakerInternalMap.this.clear();
3882    }
3883  }
3884
3885  final class EntrySet extends AbstractSet<Entry<K, V>> {
3886
3887    @Override
3888    public Iterator<Entry<K, V>> iterator() {
3889      return new EntryIterator();
3890    }
3891
3892    @Override
3893    public boolean contains(Object o) {
3894      if (!(o instanceof Entry)) {
3895        return false;
3896      }
3897      Entry<?, ?> e = (Entry<?, ?>) o;
3898      Object key = e.getKey();
3899      if (key == null) {
3900        return false;
3901      }
3902      V v = MapMakerInternalMap.this.get(key);
3903
3904      return v != null && valueEquivalence.equivalent(e.getValue(), v);
3905    }
3906
3907    @Override
3908    public boolean remove(Object o) {
3909      if (!(o instanceof Entry)) {
3910        return false;
3911      }
3912      Entry<?, ?> e = (Entry<?, ?>) o;
3913      Object key = e.getKey();
3914      return key != null && MapMakerInternalMap.this.remove(key, e.getValue());
3915    }
3916
3917    @Override
3918    public int size() {
3919      return MapMakerInternalMap.this.size();
3920    }
3921
3922    @Override
3923    public boolean isEmpty() {
3924      return MapMakerInternalMap.this.isEmpty();
3925    }
3926
3927    @Override
3928    public void clear() {
3929      MapMakerInternalMap.this.clear();
3930    }
3931  }
3932
3933  // Serialization Support
3934
3935  private static final long serialVersionUID = 5;
3936
3937  Object writeReplace() {
3938    return new SerializationProxy<K, V>(keyStrength, valueStrength, keyEquivalence,
3939        valueEquivalence, expireAfterWriteNanos, expireAfterAccessNanos, maximumSize,
3940        concurrencyLevel, removalListener, this);
3941  }
3942
3943  /**
3944   * The actual object that gets serialized. Unfortunately, readResolve() doesn't get called when a
3945   * circular dependency is present, so the proxy must be able to behave as the map itself.
3946   */
3947  abstract static class AbstractSerializationProxy<K, V>
3948      extends ForwardingConcurrentMap<K, V> implements Serializable {
3949    private static final long serialVersionUID = 3;
3950
3951    final Strength keyStrength;
3952    final Strength valueStrength;
3953    final Equivalence<Object> keyEquivalence;
3954    final Equivalence<Object> valueEquivalence;
3955    final long expireAfterWriteNanos;
3956    final long expireAfterAccessNanos;
3957    final int maximumSize;
3958    final int concurrencyLevel;
3959    final RemovalListener<? super K, ? super V> removalListener;
3960
3961    transient ConcurrentMap<K, V> delegate;
3962
3963    AbstractSerializationProxy(Strength keyStrength, Strength valueStrength,
3964        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
3965        long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
3966        int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
3967        ConcurrentMap<K, V> delegate) {
3968      this.keyStrength = keyStrength;
3969      this.valueStrength = valueStrength;
3970      this.keyEquivalence = keyEquivalence;
3971      this.valueEquivalence = valueEquivalence;
3972      this.expireAfterWriteNanos = expireAfterWriteNanos;
3973      this.expireAfterAccessNanos = expireAfterAccessNanos;
3974      this.maximumSize = maximumSize;
3975      this.concurrencyLevel = concurrencyLevel;
3976      this.removalListener = removalListener;
3977      this.delegate = delegate;
3978    }
3979
3980    @Override
3981    protected ConcurrentMap<K, V> delegate() {
3982      return delegate;
3983    }
3984
3985    void writeMapTo(ObjectOutputStream out) throws IOException {
3986      out.writeInt(delegate.size());
3987      for (Entry<K, V> entry : delegate.entrySet()) {
3988        out.writeObject(entry.getKey());
3989        out.writeObject(entry.getValue());
3990      }
3991      out.writeObject(null); // terminate entries
3992    }
3993
3994    @SuppressWarnings("deprecation") // serialization of deprecated feature
3995    MapMaker readMapMaker(ObjectInputStream in) throws IOException {
3996      int size = in.readInt();
3997      MapMaker mapMaker = new MapMaker()
3998          .initialCapacity(size)
3999          .setKeyStrength(keyStrength)
4000          .setValueStrength(valueStrength)
4001          .keyEquivalence(keyEquivalence)
4002          .valueEquivalence(valueEquivalence)
4003          .concurrencyLevel(concurrencyLevel);
4004      mapMaker.removalListener(removalListener);
4005      if (expireAfterWriteNanos > 0) {
4006        mapMaker.expireAfterWrite(expireAfterWriteNanos, TimeUnit.NANOSECONDS);
4007      }
4008      if (expireAfterAccessNanos > 0) {
4009        mapMaker.expireAfterAccess(expireAfterAccessNanos, TimeUnit.NANOSECONDS);
4010      }
4011      if (maximumSize != MapMaker.UNSET_INT) {
4012        mapMaker.maximumSize(maximumSize);
4013      }
4014      return mapMaker;
4015    }
4016
4017    @SuppressWarnings("unchecked")
4018    void readEntries(ObjectInputStream in) throws IOException, ClassNotFoundException {
4019      while (true) {
4020        K key = (K) in.readObject();
4021        if (key == null) {
4022          break; // terminator
4023        }
4024        V value = (V) in.readObject();
4025        delegate.put(key, value);
4026      }
4027    }
4028  }
4029
4030  /**
4031   * The actual object that gets serialized. Unfortunately, readResolve() doesn't get called when a
4032   * circular dependency is present, so the proxy must be able to behave as the map itself.
4033   */
4034  private static final class SerializationProxy<K, V> extends AbstractSerializationProxy<K, V> {
4035    private static final long serialVersionUID = 3;
4036
4037    SerializationProxy(Strength keyStrength, Strength valueStrength,
4038        Equivalence<Object> keyEquivalence, Equivalence<Object> valueEquivalence,
4039        long expireAfterWriteNanos, long expireAfterAccessNanos, int maximumSize,
4040        int concurrencyLevel, RemovalListener<? super K, ? super V> removalListener,
4041        ConcurrentMap<K, V> delegate) {
4042      super(keyStrength, valueStrength, keyEquivalence, valueEquivalence, expireAfterWriteNanos,
4043          expireAfterAccessNanos, maximumSize, concurrencyLevel, removalListener, delegate);
4044    }
4045
4046    private void writeObject(ObjectOutputStream out) throws IOException {
4047      out.defaultWriteObject();
4048      writeMapTo(out);
4049    }
4050
4051    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
4052      in.defaultReadObject();
4053      MapMaker mapMaker = readMapMaker(in);
4054      delegate = mapMaker.makeMap();
4055      readEntries(in);
4056    }
4057
4058    private Object readResolve() {
4059      return delegate;
4060    }
4061  }
4062}
4063