Coverage Summary for Class: MapMakerInternalMap (com.google.common.collect)

Class Method, % Line, %
MapMakerInternalMap 0% (0/38) 0% (0/163)
MapMakerInternalMap$1 0% (0/4) 0% (0/4)
MapMakerInternalMap$AbstractSerializationProxy 0% (0/5) 0% (0/27)
MapMakerInternalMap$AbstractStrongKeyEntry 0% (0/4) 0% (0/7)
MapMakerInternalMap$AbstractWeakKeyEntry 0% (0/4) 0% (0/6)
MapMakerInternalMap$CleanupMapTask 0% (0/2) 0% (0/7)
MapMakerInternalMap$DummyInternalEntry 0% (0/5) 0% (0/6)
MapMakerInternalMap$EntryIterator 0% (0/2) 0% (0/2)
MapMakerInternalMap$EntrySet 0% (0/7) 0% (0/18)
MapMakerInternalMap$HashIterator 0% (0/8) 0% (0/40)
MapMakerInternalMap$KeyIterator 0% (0/2) 0% (0/2)
MapMakerInternalMap$KeySet 0% (0/7) 0% (0/7)
MapMakerInternalMap$SafeToArraySet 0% (0/3) 0% (0/3)
MapMakerInternalMap$Segment 0% (0/45) 0% (0/355)
MapMakerInternalMap$SerializationProxy 0% (0/4) 0% (0/8)
MapMakerInternalMap$Strength 0% (0/1) 0% (0/3)
MapMakerInternalMap$Strength$1 0% (0/2) 0% (0/2)
MapMakerInternalMap$Strength$2 0% (0/2) 0% (0/2)
MapMakerInternalMap$StrongKeyDummyValueEntry 0% (0/3) 0% (0/3)
MapMakerInternalMap$StrongKeyDummyValueEntry$Helper 0% (0/8) 0% (0/8)
MapMakerInternalMap$StrongKeyDummyValueSegment 0% (0/3) 0% (0/3)
MapMakerInternalMap$StrongKeyStrongValueEntry 0% (0/4) 0% (0/7)
MapMakerInternalMap$StrongKeyStrongValueEntry$Helper 0% (0/9) 0% (0/9)
MapMakerInternalMap$StrongKeyStrongValueSegment 0% (0/3) 0% (0/3)
MapMakerInternalMap$StrongKeyWeakValueEntry 0% (0/7) 0% (0/13)
MapMakerInternalMap$StrongKeyWeakValueEntry$Helper 0% (0/9) 0% (0/11)
MapMakerInternalMap$StrongKeyWeakValueSegment 0% (0/10) 0% (0/15)
MapMakerInternalMap$ValueIterator 0% (0/2) 0% (0/2)
MapMakerInternalMap$Values 0% (0/8) 0% (0/8)
MapMakerInternalMap$WeakKeyDummyValueEntry 0% (0/3) 0% (0/3)
MapMakerInternalMap$WeakKeyDummyValueEntry$Helper 0% (0/8) 0% (0/10)
MapMakerInternalMap$WeakKeyDummyValueSegment 0% (0/7) 0% (0/8)
MapMakerInternalMap$WeakKeyStrongValueEntry 0% (0/4) 0% (0/8)
MapMakerInternalMap$WeakKeyStrongValueEntry$Helper 0% (0/9) 0% (0/11)
MapMakerInternalMap$WeakKeyStrongValueSegment 0% (0/7) 0% (0/8)
MapMakerInternalMap$WeakKeyWeakValueEntry 0% (0/7) 0% (0/14)
MapMakerInternalMap$WeakKeyWeakValueEntry$Helper 0% (0/9) 0% (0/13)
MapMakerInternalMap$WeakKeyWeakValueSegment 0% (0/11) 0% (0/18)
MapMakerInternalMap$WeakValueReferenceImpl 0% (0/3) 0% (0/4)
MapMakerInternalMap$WriteThroughEntry 0% (0/6) 0% (0/13)
Total 0% (0/285) 0% (0/854)


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  15 package com.google.common.collect; 16  17 import static com.google.common.base.Preconditions.checkNotNull; 18 import static com.google.common.collect.CollectPreconditions.checkRemove; 19  20 import com.google.common.annotations.GwtIncompatible; 21 import com.google.common.annotations.VisibleForTesting; 22 import com.google.common.base.Equivalence; 23 import com.google.common.collect.MapMaker.Dummy; 24 import com.google.common.primitives.Ints; 25 import com.google.errorprone.annotations.CanIgnoreReturnValue; 26 import com.google.errorprone.annotations.concurrent.GuardedBy; 27 import com.google.j2objc.annotations.Weak; 28 import com.google.j2objc.annotations.WeakOuter; 29 import java.io.IOException; 30 import java.io.ObjectInputStream; 31 import java.io.ObjectOutputStream; 32 import java.io.Serializable; 33 import java.lang.ref.Reference; 34 import java.lang.ref.ReferenceQueue; 35 import java.lang.ref.WeakReference; 36 import java.util.AbstractCollection; 37 import java.util.AbstractMap; 38 import java.util.AbstractSet; 39 import java.util.ArrayList; 40 import java.util.Collection; 41 import java.util.Iterator; 42 import java.util.Map; 43 import java.util.NoSuchElementException; 44 import java.util.Set; 45 import java.util.concurrent.CancellationException; 46 import java.util.concurrent.ConcurrentMap; 47 import java.util.concurrent.atomic.AtomicInteger; 48 import java.util.concurrent.atomic.AtomicReferenceArray; 49 import java.util.concurrent.locks.ReentrantLock; 50 import org.checkerframework.checker.nullness.qual.Nullable; 51  52 /** 53  * The concurrent hash map implementation built by {@link MapMaker}. 54  * 55  * <p>This implementation is heavily derived from revision 1.96 of <a 56  * href="http://tinyurl.com/ConcurrentHashMap">ConcurrentHashMap.java</a>. 57  * 58  * @param <K> the type of the keys in the map 59  * @param <V> the type of the values in the map 60  * @param <E> the type of the {@link InternalEntry} entry implementation used internally 61  * @param <S> the type of the {@link Segment} entry implementation used internally 62  * @author Bob Lee 63  * @author Charles Fry 64  * @author Doug Lea ({@code ConcurrentHashMap}) 65  */ 66 // TODO(kak): Consider removing @CanIgnoreReturnValue from this class. 67 @GwtIncompatible 68 @SuppressWarnings("GuardedBy") // TODO(b/35466881): Fix or suppress. 69 class MapMakerInternalMap< 70  K, 71  V, 72  E extends MapMakerInternalMap.InternalEntry<K, V, E>, 73  S extends MapMakerInternalMap.Segment<K, V, E, S>> 74  extends AbstractMap<K, V> implements ConcurrentMap<K, V>, Serializable { 75  76  /* 77  * The basic strategy is to subdivide the table among Segments, each of which itself is a 78  * concurrently readable hash table. The map supports non-blocking reads and concurrent writes 79  * across different segments. 80  * 81  * The page replacement algorithm's data structures are kept casually consistent with the map. The 82  * ordering of writes to a segment is sequentially consistent. An update to the map and recording 83  * of reads may not be immediately reflected on the algorithm's data structures. These structures 84  * are guarded by a lock and operations are applied in batches to avoid lock contention. The 85  * penalty of applying the batches is spread across threads so that the amortized cost is slightly 86  * higher than performing just the operation without enforcing the capacity constraint. 87  * 88  * This implementation uses a per-segment queue to record a memento of the additions, removals, 89  * and accesses that were performed on the map. The queue is drained on writes and when it exceeds 90  * its capacity threshold. 91  * 92  * The Least Recently Used page replacement algorithm was chosen due to its simplicity, high hit 93  * rate, and ability to be implemented with O(1) time complexity. The initial LRU implementation 94  * operates per-segment rather than globally for increased implementation simplicity. We expect 95  * the cache hit rate to be similar to that of a global LRU algorithm. 96  */ 97  98  // Constants 99  100  /** 101  * The maximum capacity, used if a higher value is implicitly specified by either of the 102  * constructors with arguments. MUST be a power of two no greater than {@code 1<<30} to ensure 103  * that entries are indexable using ints. 104  */ 105  static final int MAXIMUM_CAPACITY = Ints.MAX_POWER_OF_TWO; 106  107  /** The maximum number of segments to allow; used to bound constructor arguments. */ 108  static final int MAX_SEGMENTS = 1 << 16; // slightly conservative 109  110  /** Number of (unsynchronized) retries in the containsValue method. */ 111  static final int CONTAINS_VALUE_RETRIES = 3; 112  113  /** 114  * Number of cache access operations that can be buffered per segment before the cache's recency 115  * ordering information is updated. This is used to avoid lock contention by recording a memento 116  * of reads and delaying a lock acquisition until the threshold is crossed or a mutation occurs. 117  * 118  * <p>This must be a (2^n)-1 as it is used as a mask. 119  */ 120  static final int DRAIN_THRESHOLD = 0x3F; 121  122  /** 123  * Maximum number of entries to be drained in a single cleanup run. This applies independently to 124  * the cleanup queue and both reference queues. 125  */ 126  // TODO(fry): empirically optimize this 127  static final int DRAIN_MAX = 16; 128  129  static final long CLEANUP_EXECUTOR_DELAY_SECS = 60; 130  131  // Fields 132  133  /** 134  * Mask value for indexing into segments. The upper bits of a key's hash code are used to choose 135  * the segment. 136  */ 137  final transient int segmentMask; 138  139  /** 140  * Shift value for indexing within segments. Helps prevent entries that end up in the same segment 141  * from also ending up in the same bucket. 142  */ 143  final transient int segmentShift; 144  145  /** The segments, each of which is a specialized hash table. */ 146  final transient Segment<K, V, E, S>[] segments; 147  148  /** The concurrency level. */ 149  final int concurrencyLevel; 150  151  /** Strategy for comparing keys. */ 152  final Equivalence<Object> keyEquivalence; 153  154  /** Strategy for handling entries and segments in a type-safe and efficient manner. */ 155  final transient InternalEntryHelper<K, V, E, S> entryHelper; 156  157  /** 158  * Creates a new, empty map with the specified strategy, initial capacity and concurrency level. 159  */ 160  private MapMakerInternalMap(MapMaker builder, InternalEntryHelper<K, V, E, S> entryHelper) { 161  concurrencyLevel = Math.min(builder.getConcurrencyLevel(), MAX_SEGMENTS); 162  163  keyEquivalence = builder.getKeyEquivalence(); 164  this.entryHelper = entryHelper; 165  166  int initialCapacity = Math.min(builder.getInitialCapacity(), MAXIMUM_CAPACITY); 167  168  // Find power-of-two sizes best matching arguments. Constraints: 169  // (segmentCount > concurrencyLevel) 170  int segmentShift = 0; 171  int segmentCount = 1; 172  while (segmentCount < concurrencyLevel) { 173  ++segmentShift; 174  segmentCount <<= 1; 175  } 176  this.segmentShift = 32 - segmentShift; 177  segmentMask = segmentCount - 1; 178  179  this.segments = newSegmentArray(segmentCount); 180  181  int segmentCapacity = initialCapacity / segmentCount; 182  if (segmentCapacity * segmentCount < initialCapacity) { 183  ++segmentCapacity; 184  } 185  186  int segmentSize = 1; 187  while (segmentSize < segmentCapacity) { 188  segmentSize <<= 1; 189  } 190  191  for (int i = 0; i < this.segments.length; ++i) { 192  this.segments[i] = createSegment(segmentSize, MapMaker.UNSET_INT); 193  } 194  } 195  196  /** Returns a fresh {@link MapMakerInternalMap} as specified by the given {@code builder}. */ 197  static <K, V> MapMakerInternalMap<K, V, ? extends InternalEntry<K, V, ?>, ?> create( 198  MapMaker builder) { 199  if (builder.getKeyStrength() == Strength.STRONG 200  && builder.getValueStrength() == Strength.STRONG) { 201  return new MapMakerInternalMap<>(builder, StrongKeyStrongValueEntry.Helper.<K, V>instance()); 202  } 203  if (builder.getKeyStrength() == Strength.STRONG 204  && builder.getValueStrength() == Strength.WEAK) { 205  return new MapMakerInternalMap<>(builder, StrongKeyWeakValueEntry.Helper.<K, V>instance()); 206  } 207  if (builder.getKeyStrength() == Strength.WEAK 208  && builder.getValueStrength() == Strength.STRONG) { 209  return new MapMakerInternalMap<>(builder, WeakKeyStrongValueEntry.Helper.<K, V>instance()); 210  } 211  if (builder.getKeyStrength() == Strength.WEAK && builder.getValueStrength() == Strength.WEAK) { 212  return new MapMakerInternalMap<>(builder, WeakKeyWeakValueEntry.Helper.<K, V>instance()); 213  } 214  throw new AssertionError(); 215  } 216  217  /** 218  * Returns a fresh {@link MapMakerInternalMap} with {@link MapMaker.Dummy} values but otherwise as 219  * specified by the given {@code builder}. The returned {@link MapMakerInternalMap} will be 220  * optimized to saved memory. Since {@link MapMaker.Dummy} is a singleton, we don't need to store 221  * any values at all. Because of this optimization, {@code build.getValueStrength()} must be 222  * {@link Strength#STRONG}. 223  * 224  * <p>This method is intended to only be used by the internal implementation of {@link Interners}, 225  * since a map of dummy values is the exact use case there. 226  */ 227  static <K> 228  MapMakerInternalMap<K, Dummy, ? extends InternalEntry<K, Dummy, ?>, ?> createWithDummyValues( 229  MapMaker builder) { 230  if (builder.getKeyStrength() == Strength.STRONG 231  && builder.getValueStrength() == Strength.STRONG) { 232  return new MapMakerInternalMap<>(builder, StrongKeyDummyValueEntry.Helper.<K>instance()); 233  } 234  if (builder.getKeyStrength() == Strength.WEAK 235  && builder.getValueStrength() == Strength.STRONG) { 236  return new MapMakerInternalMap<>(builder, WeakKeyDummyValueEntry.Helper.<K>instance()); 237  } 238  if (builder.getValueStrength() == Strength.WEAK) { 239  throw new IllegalArgumentException("Map cannot have both weak and dummy values"); 240  } 241  throw new AssertionError(); 242  } 243  244  enum Strength { 245  STRONG { 246  @Override 247  Equivalence<Object> defaultEquivalence() { 248  return Equivalence.equals(); 249  } 250  }, 251  252  WEAK { 253  @Override 254  Equivalence<Object> defaultEquivalence() { 255  return Equivalence.identity(); 256  } 257  }; 258  259  /** 260  * Returns the default equivalence strategy used to compare and hash keys or values referenced 261  * at this strength. This strategy will be used unless the user explicitly specifies an 262  * alternate strategy. 263  */ 264  abstract Equivalence<Object> defaultEquivalence(); 265  } 266  267  /** 268  * A helper object for operating on {@link InternalEntry} instances in a type-safe and efficient 269  * manner. 270  * 271  * <p>For each of the four combinations of strong/weak key and strong/weak value, there are 272  * corresponding {@link InternalEntry}, {@link Segment}, and {@link InternalEntryHelper} 273  * implementations. 274  * 275  * @param <K> the type of the key in each entry 276  * @param <V> the type of the value in each entry 277  * @param <E> the type of the {@link InternalEntry} entry implementation 278  * @param <S> the type of the {@link Segment} entry implementation 279  */ 280  interface InternalEntryHelper< 281  K, V, E extends InternalEntry<K, V, E>, S extends Segment<K, V, E, S>> { 282  /** The strength of the key type in each entry. */ 283  Strength keyStrength(); 284  285  /** The strength of the value type in each entry. */ 286  Strength valueStrength(); 287  288  /** Returns a freshly created segment, typed at the {@code S} type. */ 289  S newSegment(MapMakerInternalMap<K, V, E, S> map, int initialCapacity, int maxSegmentSize); 290  291  /** 292  * Returns a freshly created entry, typed at the {@code E} type, for the given {@code segment}. 293  */ 294  E newEntry(S segment, K key, int hash, @Nullable E next); 295  296  /** 297  * Returns a freshly created entry, typed at the {@code E} type, for the given {@code segment}, 298  * that is a copy of the given {@code entry}. 299  */ 300  E copy(S segment, E entry, @Nullable E newNext); 301  302  /** 303  * Sets the value of the given {@code entry} in the given {@code segment} to be the given {@code 304  * value} 305  */ 306  void setValue(S segment, E entry, V value); 307  } 308  309  /** 310  * An entry in a hash table of a {@link Segment}. 311  * 312  * <p>Entries in the map can be in the following states: 313  * 314  * <p>Valid: - Live: valid key/value are set 315  * 316  * <p>Invalid: - Collected: key/value was partially collected, but not yet cleaned up 317  */ 318  interface InternalEntry<K, V, E extends InternalEntry<K, V, E>> { 319  /** Gets the next entry in the chain. */ 320  E getNext(); 321  322  /** Gets the entry's hash. */ 323  int getHash(); 324  325  /** Gets the key for this entry. */ 326  K getKey(); 327  328  /** Gets the value for the entry. */ 329  V getValue(); 330  } 331  332  /* 333  * Note: the following classes have a lot of duplicate code. It sucks, but it saves a lot of 334  * memory. If only Java had mixins! 335  */ 336  337  /** Base class for {@link InternalEntry} implementations for strong keys. */ 338  abstract static class AbstractStrongKeyEntry<K, V, E extends InternalEntry<K, V, E>> 339  implements InternalEntry<K, V, E> { 340  final K key; 341  final int hash; 342  final @Nullable E next; 343  344  AbstractStrongKeyEntry(K key, int hash, @Nullable E next) { 345  this.key = key; 346  this.hash = hash; 347  this.next = next; 348  } 349  350  @Override 351  public K getKey() { 352  return this.key; 353  } 354  355  @Override 356  public int getHash() { 357  return hash; 358  } 359  360  @Override 361  public E getNext() { 362  return next; 363  } 364  } 365  366  /** Marker interface for {@link InternalEntry} implementations for strong values. */ 367  interface StrongValueEntry<K, V, E extends InternalEntry<K, V, E>> 368  extends InternalEntry<K, V, E> {} 369  370  /** Marker interface for {@link InternalEntry} implementations for weak values. */ 371  interface WeakValueEntry<K, V, E extends InternalEntry<K, V, E>> extends InternalEntry<K, V, E> { 372  /** Gets the weak value reference held by entry. */ 373  WeakValueReference<K, V, E> getValueReference(); 374  375  /** 376  * Clears the weak value reference held by the entry. Should be used when the entry's value is 377  * overwritten. 378  */ 379  void clearValue(); 380  } 381  382  @SuppressWarnings("unchecked") // impl never uses a parameter or returns any non-null value 383  static <K, V, E extends InternalEntry<K, V, E>> 384  WeakValueReference<K, V, E> unsetWeakValueReference() { 385  return (WeakValueReference<K, V, E>) UNSET_WEAK_VALUE_REFERENCE; 386  } 387  388  /** Concrete implementation of {@link InternalEntry} for strong keys and strong values. */ 389  static final class StrongKeyStrongValueEntry<K, V> 390  extends AbstractStrongKeyEntry<K, V, StrongKeyStrongValueEntry<K, V>> 391  implements StrongValueEntry<K, V, StrongKeyStrongValueEntry<K, V>> { 392  private volatile @Nullable V value = null; 393  394  StrongKeyStrongValueEntry(K key, int hash, @Nullable StrongKeyStrongValueEntry<K, V> next) { 395  super(key, hash, next); 396  } 397  398  @Override 399  public @Nullable V getValue() { 400  return value; 401  } 402  403  void setValue(V value) { 404  this.value = value; 405  } 406  407  StrongKeyStrongValueEntry<K, V> copy(StrongKeyStrongValueEntry<K, V> newNext) { 408  StrongKeyStrongValueEntry<K, V> newEntry = 409  new StrongKeyStrongValueEntry<>(this.key, this.hash, newNext); 410  newEntry.value = this.value; 411  return newEntry; 412  } 413  414  /** Concrete implementation of {@link InternalEntryHelper} for strong keys and strong values. */ 415  static final class Helper<K, V> 416  implements InternalEntryHelper< 417  K, V, StrongKeyStrongValueEntry<K, V>, StrongKeyStrongValueSegment<K, V>> { 418  private static final Helper<?, ?> INSTANCE = new Helper<>(); 419  420  @SuppressWarnings("unchecked") 421  static <K, V> Helper<K, V> instance() { 422  return (Helper<K, V>) INSTANCE; 423  } 424  425  @Override 426  public Strength keyStrength() { 427  return Strength.STRONG; 428  } 429  430  @Override 431  public Strength valueStrength() { 432  return Strength.STRONG; 433  } 434  435  @Override 436  public StrongKeyStrongValueSegment<K, V> newSegment( 437  MapMakerInternalMap< 438  K, V, StrongKeyStrongValueEntry<K, V>, StrongKeyStrongValueSegment<K, V>> 439  map, 440  int initialCapacity, 441  int maxSegmentSize) { 442  return new StrongKeyStrongValueSegment<>(map, initialCapacity, maxSegmentSize); 443  } 444  445  @Override 446  public StrongKeyStrongValueEntry<K, V> copy( 447  StrongKeyStrongValueSegment<K, V> segment, 448  StrongKeyStrongValueEntry<K, V> entry, 449  @Nullable StrongKeyStrongValueEntry<K, V> newNext) { 450  return entry.copy(newNext); 451  } 452  453  @Override 454  public void setValue( 455  StrongKeyStrongValueSegment<K, V> segment, 456  StrongKeyStrongValueEntry<K, V> entry, 457  V value) { 458  entry.setValue(value); 459  } 460  461  @Override 462  public StrongKeyStrongValueEntry<K, V> newEntry( 463  StrongKeyStrongValueSegment<K, V> segment, 464  K key, 465  int hash, 466  @Nullable StrongKeyStrongValueEntry<K, V> next) { 467  return new StrongKeyStrongValueEntry<>(key, hash, next); 468  } 469  } 470  } 471  472  /** Concrete implementation of {@link InternalEntry} for strong keys and weak values. */ 473  static final class StrongKeyWeakValueEntry<K, V> 474  extends AbstractStrongKeyEntry<K, V, StrongKeyWeakValueEntry<K, V>> 475  implements WeakValueEntry<K, V, StrongKeyWeakValueEntry<K, V>> { 476  private volatile WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> valueReference = 477  unsetWeakValueReference(); 478  479  StrongKeyWeakValueEntry(K key, int hash, @Nullable StrongKeyWeakValueEntry<K, V> next) { 480  super(key, hash, next); 481  } 482  483  @Override 484  public V getValue() { 485  return valueReference.get(); 486  } 487  488  @Override 489  public void clearValue() { 490  valueReference.clear(); 491  } 492  493  void setValue(V value, ReferenceQueue<V> queueForValues) { 494  WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> previous = this.valueReference; 495  this.valueReference = new WeakValueReferenceImpl<>(queueForValues, value, this); 496  previous.clear(); 497  } 498  499  StrongKeyWeakValueEntry<K, V> copy( 500  ReferenceQueue<V> queueForValues, StrongKeyWeakValueEntry<K, V> newNext) { 501  StrongKeyWeakValueEntry<K, V> newEntry = new StrongKeyWeakValueEntry<>(key, hash, newNext); 502  newEntry.valueReference = valueReference.copyFor(queueForValues, newEntry); 503  return newEntry; 504  } 505  506  @Override 507  public WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> getValueReference() { 508  return valueReference; 509  } 510  511  /** Concrete implementation of {@link InternalEntryHelper} for strong keys and weak values. */ 512  static final class Helper<K, V> 513  implements InternalEntryHelper< 514  K, V, StrongKeyWeakValueEntry<K, V>, StrongKeyWeakValueSegment<K, V>> { 515  private static final Helper<?, ?> INSTANCE = new Helper<>(); 516  517  @SuppressWarnings("unchecked") 518  static <K, V> Helper<K, V> instance() { 519  return (Helper<K, V>) INSTANCE; 520  } 521  522  @Override 523  public Strength keyStrength() { 524  return Strength.STRONG; 525  } 526  527  @Override 528  public Strength valueStrength() { 529  return Strength.WEAK; 530  } 531  532  @Override 533  public StrongKeyWeakValueSegment<K, V> newSegment( 534  MapMakerInternalMap<K, V, StrongKeyWeakValueEntry<K, V>, StrongKeyWeakValueSegment<K, V>> 535  map, 536  int initialCapacity, 537  int maxSegmentSize) { 538  return new StrongKeyWeakValueSegment<>(map, initialCapacity, maxSegmentSize); 539  } 540  541  @Override 542  public StrongKeyWeakValueEntry<K, V> copy( 543  StrongKeyWeakValueSegment<K, V> segment, 544  StrongKeyWeakValueEntry<K, V> entry, 545  @Nullable StrongKeyWeakValueEntry<K, V> newNext) { 546  if (Segment.isCollected(entry)) { 547  return null; 548  } 549  return entry.copy(segment.queueForValues, newNext); 550  } 551  552  @Override 553  public void setValue( 554  StrongKeyWeakValueSegment<K, V> segment, StrongKeyWeakValueEntry<K, V> entry, V value) { 555  entry.setValue(value, segment.queueForValues); 556  } 557  558  @Override 559  public StrongKeyWeakValueEntry<K, V> newEntry( 560  StrongKeyWeakValueSegment<K, V> segment, 561  K key, 562  int hash, 563  @Nullable StrongKeyWeakValueEntry<K, V> next) { 564  return new StrongKeyWeakValueEntry<>(key, hash, next); 565  } 566  } 567  } 568  569  /** Concrete implementation of {@link InternalEntry} for strong keys and {@link Dummy} values. */ 570  static final class StrongKeyDummyValueEntry<K> 571  extends AbstractStrongKeyEntry<K, Dummy, StrongKeyDummyValueEntry<K>> 572  implements StrongValueEntry<K, Dummy, StrongKeyDummyValueEntry<K>> { 573  StrongKeyDummyValueEntry(K key, int hash, @Nullable StrongKeyDummyValueEntry<K> next) { 574  super(key, hash, next); 575  } 576  577  @Override 578  public Dummy getValue() { 579  return Dummy.VALUE; 580  } 581  582  void setValue(Dummy value) {} 583  584  StrongKeyDummyValueEntry<K> copy(StrongKeyDummyValueEntry<K> newNext) { 585  return new StrongKeyDummyValueEntry<K>(this.key, this.hash, newNext); 586  } 587  588  /** 589  * Concrete implementation of {@link InternalEntryHelper} for strong keys and {@link Dummy} 590  * values. 591  */ 592  static final class Helper<K> 593  implements InternalEntryHelper< 594  K, Dummy, StrongKeyDummyValueEntry<K>, StrongKeyDummyValueSegment<K>> { 595  private static final Helper<?> INSTANCE = new Helper<>(); 596  597  @SuppressWarnings("unchecked") 598  static <K> Helper<K> instance() { 599  return (Helper<K>) INSTANCE; 600  } 601  602  @Override 603  public Strength keyStrength() { 604  return Strength.STRONG; 605  } 606  607  @Override 608  public Strength valueStrength() { 609  return Strength.STRONG; 610  } 611  612  @Override 613  public StrongKeyDummyValueSegment<K> newSegment( 614  MapMakerInternalMap<K, Dummy, StrongKeyDummyValueEntry<K>, StrongKeyDummyValueSegment<K>> 615  map, 616  int initialCapacity, 617  int maxSegmentSize) { 618  return new StrongKeyDummyValueSegment<K>(map, initialCapacity, maxSegmentSize); 619  } 620  621  @Override 622  public StrongKeyDummyValueEntry<K> copy( 623  StrongKeyDummyValueSegment<K> segment, 624  StrongKeyDummyValueEntry<K> entry, 625  @Nullable StrongKeyDummyValueEntry<K> newNext) { 626  return entry.copy(newNext); 627  } 628  629  @Override 630  public void setValue( 631  StrongKeyDummyValueSegment<K> segment, StrongKeyDummyValueEntry<K> entry, Dummy value) {} 632  633  @Override 634  public StrongKeyDummyValueEntry<K> newEntry( 635  StrongKeyDummyValueSegment<K> segment, 636  K key, 637  int hash, 638  @Nullable StrongKeyDummyValueEntry<K> next) { 639  return new StrongKeyDummyValueEntry<K>(key, hash, next); 640  } 641  } 642  } 643  644  /** Base class for {@link InternalEntry} implementations for weak keys. */ 645  abstract static class AbstractWeakKeyEntry<K, V, E extends InternalEntry<K, V, E>> 646  extends WeakReference<K> implements InternalEntry<K, V, E> { 647  final int hash; 648  final @Nullable E next; 649  650  AbstractWeakKeyEntry(ReferenceQueue<K> queue, K key, int hash, @Nullable E next) { 651  super(key, queue); 652  this.hash = hash; 653  this.next = next; 654  } 655  656  @Override 657  public K getKey() { 658  return get(); 659  } 660  661  @Override 662  public int getHash() { 663  return hash; 664  } 665  666  @Override 667  public E getNext() { 668  return next; 669  } 670  } 671  672  /** Concrete implementation of {@link InternalEntry} for weak keys and {@link Dummy} values. */ 673  static final class WeakKeyDummyValueEntry<K> 674  extends AbstractWeakKeyEntry<K, Dummy, WeakKeyDummyValueEntry<K>> 675  implements StrongValueEntry<K, Dummy, WeakKeyDummyValueEntry<K>> { 676  WeakKeyDummyValueEntry( 677  ReferenceQueue<K> queue, K key, int hash, @Nullable WeakKeyDummyValueEntry<K> next) { 678  super(queue, key, hash, next); 679  } 680  681  @Override 682  public Dummy getValue() { 683  return Dummy.VALUE; 684  } 685  686  void setValue(Dummy value) {} 687  688  WeakKeyDummyValueEntry<K> copy( 689  ReferenceQueue<K> queueForKeys, WeakKeyDummyValueEntry<K> newNext) { 690  return new WeakKeyDummyValueEntry<K>(queueForKeys, getKey(), this.hash, newNext); 691  } 692  693  /** 694  * Concrete implementation of {@link InternalEntryHelper} for weak keys and {@link Dummy} 695  * values. 696  */ 697  static final class Helper<K> 698  implements InternalEntryHelper< 699  K, Dummy, WeakKeyDummyValueEntry<K>, WeakKeyDummyValueSegment<K>> { 700  private static final Helper<?> INSTANCE = new Helper<>(); 701  702  @SuppressWarnings("unchecked") 703  static <K> Helper<K> instance() { 704  return (Helper<K>) INSTANCE; 705  } 706  707  @Override 708  public Strength keyStrength() { 709  return Strength.WEAK; 710  } 711  712  @Override 713  public Strength valueStrength() { 714  return Strength.STRONG; 715  } 716  717  @Override 718  public WeakKeyDummyValueSegment<K> newSegment( 719  MapMakerInternalMap<K, Dummy, WeakKeyDummyValueEntry<K>, WeakKeyDummyValueSegment<K>> map, 720  int initialCapacity, 721  int maxSegmentSize) { 722  return new WeakKeyDummyValueSegment<K>(map, initialCapacity, maxSegmentSize); 723  } 724  725  @Override 726  public WeakKeyDummyValueEntry<K> copy( 727  WeakKeyDummyValueSegment<K> segment, 728  WeakKeyDummyValueEntry<K> entry, 729  @Nullable WeakKeyDummyValueEntry<K> newNext) { 730  if (entry.getKey() == null) { 731  // key collected 732  return null; 733  } 734  return entry.copy(segment.queueForKeys, newNext); 735  } 736  737  @Override 738  public void setValue( 739  WeakKeyDummyValueSegment<K> segment, WeakKeyDummyValueEntry<K> entry, Dummy value) {} 740  741  @Override 742  public WeakKeyDummyValueEntry<K> newEntry( 743  WeakKeyDummyValueSegment<K> segment, 744  K key, 745  int hash, 746  @Nullable WeakKeyDummyValueEntry<K> next) { 747  return new WeakKeyDummyValueEntry<K>(segment.queueForKeys, key, hash, next); 748  } 749  } 750  } 751  752  /** Concrete implementation of {@link InternalEntry} for weak keys and strong values. */ 753  static final class WeakKeyStrongValueEntry<K, V> 754  extends AbstractWeakKeyEntry<K, V, WeakKeyStrongValueEntry<K, V>> 755  implements StrongValueEntry<K, V, WeakKeyStrongValueEntry<K, V>> { 756  private volatile @Nullable V value = null; 757  758  WeakKeyStrongValueEntry( 759  ReferenceQueue<K> queue, K key, int hash, @Nullable WeakKeyStrongValueEntry<K, V> next) { 760  super(queue, key, hash, next); 761  } 762  763  @Override 764  public @Nullable V getValue() { 765  return value; 766  } 767  768  void setValue(V value) { 769  this.value = value; 770  } 771  772  WeakKeyStrongValueEntry<K, V> copy( 773  ReferenceQueue<K> queueForKeys, WeakKeyStrongValueEntry<K, V> newNext) { 774  WeakKeyStrongValueEntry<K, V> newEntry = 775  new WeakKeyStrongValueEntry<>(queueForKeys, getKey(), this.hash, newNext); 776  newEntry.setValue(value); 777  return newEntry; 778  } 779  780  /** Concrete implementation of {@link InternalEntryHelper} for weak keys and strong values. */ 781  static final class Helper<K, V> 782  implements InternalEntryHelper< 783  K, V, WeakKeyStrongValueEntry<K, V>, WeakKeyStrongValueSegment<K, V>> { 784  private static final Helper<?, ?> INSTANCE = new Helper<>(); 785  786  @SuppressWarnings("unchecked") 787  static <K, V> Helper<K, V> instance() { 788  return (Helper<K, V>) INSTANCE; 789  } 790  791  @Override 792  public Strength keyStrength() { 793  return Strength.WEAK; 794  } 795  796  @Override 797  public Strength valueStrength() { 798  return Strength.STRONG; 799  } 800  801  @Override 802  public WeakKeyStrongValueSegment<K, V> newSegment( 803  MapMakerInternalMap<K, V, WeakKeyStrongValueEntry<K, V>, WeakKeyStrongValueSegment<K, V>> 804  map, 805  int initialCapacity, 806  int maxSegmentSize) { 807  return new WeakKeyStrongValueSegment<>(map, initialCapacity, maxSegmentSize); 808  } 809  810  @Override 811  public WeakKeyStrongValueEntry<K, V> copy( 812  WeakKeyStrongValueSegment<K, V> segment, 813  WeakKeyStrongValueEntry<K, V> entry, 814  @Nullable WeakKeyStrongValueEntry<K, V> newNext) { 815  if (entry.getKey() == null) { 816  // key collected 817  return null; 818  } 819  return entry.copy(segment.queueForKeys, newNext); 820  } 821  822  @Override 823  public void setValue( 824  WeakKeyStrongValueSegment<K, V> segment, WeakKeyStrongValueEntry<K, V> entry, V value) { 825  entry.setValue(value); 826  } 827  828  @Override 829  public WeakKeyStrongValueEntry<K, V> newEntry( 830  WeakKeyStrongValueSegment<K, V> segment, 831  K key, 832  int hash, 833  @Nullable WeakKeyStrongValueEntry<K, V> next) { 834  return new WeakKeyStrongValueEntry<>(segment.queueForKeys, key, hash, next); 835  } 836  } 837  } 838  839  /** Concrete implementation of {@link InternalEntry} for weak keys and weak values. */ 840  static final class WeakKeyWeakValueEntry<K, V> 841  extends AbstractWeakKeyEntry<K, V, WeakKeyWeakValueEntry<K, V>> 842  implements WeakValueEntry<K, V, WeakKeyWeakValueEntry<K, V>> { 843  private volatile WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> valueReference = 844  unsetWeakValueReference(); 845  846  WeakKeyWeakValueEntry( 847  ReferenceQueue<K> queue, K key, int hash, @Nullable WeakKeyWeakValueEntry<K, V> next) { 848  super(queue, key, hash, next); 849  } 850  851  @Override 852  public V getValue() { 853  return valueReference.get(); 854  } 855  856  WeakKeyWeakValueEntry<K, V> copy( 857  ReferenceQueue<K> queueForKeys, 858  ReferenceQueue<V> queueForValues, 859  WeakKeyWeakValueEntry<K, V> newNext) { 860  WeakKeyWeakValueEntry<K, V> newEntry = 861  new WeakKeyWeakValueEntry<>(queueForKeys, getKey(), this.hash, newNext); 862  newEntry.valueReference = valueReference.copyFor(queueForValues, newEntry); 863  return newEntry; 864  } 865  866  @Override 867  public void clearValue() { 868  valueReference.clear(); 869  } 870  871  void setValue(V value, ReferenceQueue<V> queueForValues) { 872  WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> previous = this.valueReference; 873  this.valueReference = new WeakValueReferenceImpl<>(queueForValues, value, this); 874  previous.clear(); 875  } 876  877  @Override 878  public WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> getValueReference() { 879  return valueReference; 880  } 881  882  /** Concrete implementation of {@link InternalEntryHelper} for weak keys and weak values. */ 883  static final class Helper<K, V> 884  implements InternalEntryHelper< 885  K, V, WeakKeyWeakValueEntry<K, V>, WeakKeyWeakValueSegment<K, V>> { 886  private static final Helper<?, ?> INSTANCE = new Helper<>(); 887  888  @SuppressWarnings("unchecked") 889  static <K, V> Helper<K, V> instance() { 890  return (Helper<K, V>) INSTANCE; 891  } 892  893  @Override 894  public Strength keyStrength() { 895  return Strength.WEAK; 896  } 897  898  @Override 899  public Strength valueStrength() { 900  return Strength.WEAK; 901  } 902  903  @Override 904  public WeakKeyWeakValueSegment<K, V> newSegment( 905  MapMakerInternalMap<K, V, WeakKeyWeakValueEntry<K, V>, WeakKeyWeakValueSegment<K, V>> map, 906  int initialCapacity, 907  int maxSegmentSize) { 908  return new WeakKeyWeakValueSegment<>(map, initialCapacity, maxSegmentSize); 909  } 910  911  @Override 912  public WeakKeyWeakValueEntry<K, V> copy( 913  WeakKeyWeakValueSegment<K, V> segment, 914  WeakKeyWeakValueEntry<K, V> entry, 915  @Nullable WeakKeyWeakValueEntry<K, V> newNext) { 916  if (entry.getKey() == null) { 917  // key collected 918  return null; 919  } 920  if (Segment.isCollected(entry)) { 921  return null; 922  } 923  return entry.copy(segment.queueForKeys, segment.queueForValues, newNext); 924  } 925  926  @Override 927  public void setValue( 928  WeakKeyWeakValueSegment<K, V> segment, WeakKeyWeakValueEntry<K, V> entry, V value) { 929  entry.setValue(value, segment.queueForValues); 930  } 931  932  @Override 933  public WeakKeyWeakValueEntry<K, V> newEntry( 934  WeakKeyWeakValueSegment<K, V> segment, 935  K key, 936  int hash, 937  @Nullable WeakKeyWeakValueEntry<K, V> next) { 938  return new WeakKeyWeakValueEntry<>(segment.queueForKeys, key, hash, next); 939  } 940  } 941  } 942  943  /** A weakly referenced value that also has a reference to its containing entry. */ 944  interface WeakValueReference<K, V, E extends InternalEntry<K, V, E>> { 945  /** 946  * Returns the current value being referenced, or {@code null} if there is none (e.g. because 947  * either it got collected, or {@link #clear} was called, or it wasn't set in the first place). 948  */ 949  @Nullable 950  V get(); 951  952  /** Returns the entry which contains this {@link WeakValueReference}. */ 953  E getEntry(); 954  955  /** Unsets the referenced value. Subsequent calls to {@link #get} will return {@code null}. */ 956  void clear(); 957  958  /** 959  * Returns a freshly created {@link WeakValueReference} for the given {@code entry} (and on the 960  * given {@code queue} with the same value as this {@link WeakValueReference}. 961  */ 962  WeakValueReference<K, V, E> copyFor(ReferenceQueue<V> queue, E entry); 963  } 964  965  /** 966  * A dummy implementation of {@link InternalEntry}, solely for use in the type signature of {@link 967  * #UNSET_WEAK_VALUE_REFERENCE} below. 968  */ 969  static final class DummyInternalEntry 970  implements InternalEntry<Object, Object, DummyInternalEntry> { 971  private DummyInternalEntry() { 972  throw new AssertionError(); 973  } 974  975  @Override 976  public DummyInternalEntry getNext() { 977  throw new AssertionError(); 978  } 979  980  @Override 981  public int getHash() { 982  throw new AssertionError(); 983  } 984  985  @Override 986  public Object getKey() { 987  throw new AssertionError(); 988  } 989  990  @Override 991  public Object getValue() { 992  throw new AssertionError(); 993  } 994  } 995  996  /** 997  * A singleton {@link WeakValueReference} used to denote an unset value in a entry with weak 998  * values. 999  */ 1000  static final WeakValueReference<Object, Object, DummyInternalEntry> UNSET_WEAK_VALUE_REFERENCE = 1001  new WeakValueReference<Object, Object, DummyInternalEntry>() { 1002  @Override 1003  public DummyInternalEntry getEntry() { 1004  return null; 1005  } 1006  1007  @Override 1008  public void clear() {} 1009  1010  @Override 1011  public Object get() { 1012  return null; 1013  } 1014  1015  @Override 1016  public WeakValueReference<Object, Object, DummyInternalEntry> copyFor( 1017  ReferenceQueue<Object> queue, DummyInternalEntry entry) { 1018  return this; 1019  } 1020  }; 1021  1022  /** Concrete implementation of {@link WeakValueReference}. */ 1023  static final class WeakValueReferenceImpl<K, V, E extends InternalEntry<K, V, E>> 1024  extends WeakReference<V> implements WeakValueReference<K, V, E> { 1025  @Weak final E entry; 1026  1027  WeakValueReferenceImpl(ReferenceQueue<V> queue, V referent, E entry) { 1028  super(referent, queue); 1029  this.entry = entry; 1030  } 1031  1032  @Override 1033  public E getEntry() { 1034  return entry; 1035  } 1036  1037  @Override 1038  public WeakValueReference<K, V, E> copyFor(ReferenceQueue<V> queue, E entry) { 1039  return new WeakValueReferenceImpl<>(queue, get(), entry); 1040  } 1041  } 1042  1043  /** 1044  * Applies a supplemental hash function to a given hash code, which defends against poor quality 1045  * hash functions. This is critical when the concurrent hash map uses power-of-two length hash 1046  * tables, that otherwise encounter collisions for hash codes that do not differ in lower or upper 1047  * bits. 1048  * 1049  * @param h hash code 1050  */ 1051  static int rehash(int h) { 1052  // Spread bits to regularize both segment and index locations, 1053  // using variant of single-word Wang/Jenkins hash. 1054  // TODO(kevinb): use Hashing/move this to Hashing? 1055  h += (h << 15) ^ 0xffffcd7d; 1056  h ^= (h >>> 10); 1057  h += (h << 3); 1058  h ^= (h >>> 6); 1059  h += (h << 2) + (h << 14); 1060  return h ^ (h >>> 16); 1061  } 1062  1063  /** 1064  * This method is a convenience for testing. Code should call {@link Segment#copyEntry} directly. 1065  */ 1066  // Guarded By Segment.this 1067  @VisibleForTesting 1068  E copyEntry(E original, E newNext) { 1069  int hash = original.getHash(); 1070  return segmentFor(hash).copyEntry(original, newNext); 1071  } 1072  1073  int hash(Object key) { 1074  int h = keyEquivalence.hash(key); 1075  return rehash(h); 1076  } 1077  1078  void reclaimValue(WeakValueReference<K, V, E> valueReference) { 1079  E entry = valueReference.getEntry(); 1080  int hash = entry.getHash(); 1081  segmentFor(hash).reclaimValue(entry.getKey(), hash, valueReference); 1082  } 1083  1084  void reclaimKey(E entry) { 1085  int hash = entry.getHash(); 1086  segmentFor(hash).reclaimKey(entry, hash); 1087  } 1088  1089  /** 1090  * This method is a convenience for testing. Code should call {@link Segment#getLiveValue} 1091  * instead. 1092  */ 1093  @VisibleForTesting 1094  boolean isLiveForTesting(InternalEntry<K, V, ?> entry) { 1095  return segmentFor(entry.getHash()).getLiveValueForTesting(entry) != null; 1096  } 1097  1098  /** 1099  * Returns the segment that should be used for a key with the given hash. 1100  * 1101  * @param hash the hash code for the key 1102  * @return the segment 1103  */ 1104  Segment<K, V, E, S> segmentFor(int hash) { 1105  // TODO(fry): Lazily create segments? 1106  return segments[(hash >>> segmentShift) & segmentMask]; 1107  } 1108  1109  Segment<K, V, E, S> createSegment(int initialCapacity, int maxSegmentSize) { 1110  return entryHelper.newSegment(this, initialCapacity, maxSegmentSize); 1111  } 1112  1113  /** 1114  * Gets the value from an entry. Returns {@code null} if the entry is invalid, partially-collected 1115  * or computing. 1116  */ 1117  V getLiveValue(E entry) { 1118  if (entry.getKey() == null) { 1119  return null; 1120  } 1121  return entry.getValue(); 1122  } 1123  1124  @SuppressWarnings("unchecked") 1125  final Segment<K, V, E, S>[] newSegmentArray(int ssize) { 1126  return new Segment[ssize]; 1127  } 1128  1129  // Inner Classes 1130  1131  /** 1132  * Segments are specialized versions of hash tables. This subclass inherits from ReentrantLock 1133  * opportunistically, just to simplify some locking and avoid separate construction. 1134  */ 1135  @SuppressWarnings("serial") // This class is never serialized. 1136  abstract static class Segment< 1137  K, V, E extends InternalEntry<K, V, E>, S extends Segment<K, V, E, S>> 1138  extends ReentrantLock { 1139  1140  /* 1141  * Segments maintain a table of entry lists that are ALWAYS kept in a consistent state, so can 1142  * be read without locking. Next fields of nodes are immutable (final). All list additions are 1143  * performed at the front of each bin. This makes it easy to check changes, and also fast to 1144  * traverse. When nodes would otherwise be changed, new nodes are created to replace them. This 1145  * works well for hash tables since the bin lists tend to be short. (The average length is less 1146  * than two.) 1147  * 1148  * Read operations can thus proceed without locking, but rely on selected uses of volatiles to 1149  * ensure that completed write operations performed by other threads are noticed. For most 1150  * purposes, the "count" field, tracking the number of elements, serves as that volatile 1151  * variable ensuring visibility. This is convenient because this field needs to be read in many 1152  * read operations anyway: 1153  * 1154  * - All (unsynchronized) read operations must first read the "count" field, and should not 1155  * look at table entries if it is 0. 1156  * 1157  * - All (synchronized) write operations should write to the "count" field after structurally 1158  * changing any bin. The operations must not take any action that could even momentarily 1159  * cause a concurrent read operation to see inconsistent data. This is made easier by the 1160  * nature of the read operations in Map. For example, no operation can reveal that the table 1161  * has grown but the threshold has not yet been updated, so there are no atomicity requirements 1162  * for this with respect to reads. 1163  * 1164  * As a guide, all critical volatile reads and writes to the count field are marked in code 1165  * comments. 1166  */ 1167  1168  @Weak final MapMakerInternalMap<K, V, E, S> map; 1169  1170  /** 1171  * The number of live elements in this segment's region. This does not include unset elements 1172  * which are awaiting cleanup. 1173  */ 1174  volatile int count; 1175  1176  /** 1177  * Number of updates that alter the size of the table. This is used during bulk-read methods to 1178  * make sure they see a consistent snapshot: If modCounts change during a traversal of segments 1179  * computing size or checking containsValue, then we might have an inconsistent view of state so 1180  * (usually) must retry. 1181  */ 1182  int modCount; 1183  1184  /** 1185  * The table is expanded when its size exceeds this threshold. (The value of this field is 1186  * always {@code (int) (capacity * 0.75)}.) 1187  */ 1188  int threshold; 1189  1190  /** The per-segment table. */ 1191  volatile @Nullable AtomicReferenceArray<E> table; 1192  1193  /** The maximum size of this map. MapMaker.UNSET_INT if there is no maximum. */ 1194  final int maxSegmentSize; 1195  1196  /** 1197  * A counter of the number of reads since the last write, used to drain queues on a small 1198  * fraction of read operations. 1199  */ 1200  final AtomicInteger readCount = new AtomicInteger(); 1201  1202  Segment(MapMakerInternalMap<K, V, E, S> map, int initialCapacity, int maxSegmentSize) { 1203  this.map = map; 1204  this.maxSegmentSize = maxSegmentSize; 1205  initTable(newEntryArray(initialCapacity)); 1206  } 1207  1208  /** 1209  * Returns {@code this} up-casted to the specific {@link Segment} implementation type {@code S}. 1210  * 1211  * <p>This method exists so that the {@link Segment} code can be generic in terms of {@code S}, 1212  * the type of the concrete implementation. 1213  */ 1214  abstract S self(); 1215  1216  /** Drains the reference queues used by this segment, if any. */ 1217  @GuardedBy("this") 1218  void maybeDrainReferenceQueues() {} 1219  1220  /** Clears the reference queues used by this segment, if any. */ 1221  void maybeClearReferenceQueues() {} 1222  1223  /** Sets the value of the given {@code entry}. */ 1224  void setValue(E entry, V value) { 1225  this.map.entryHelper.setValue(self(), entry, value); 1226  } 1227  1228  /** Returns a copy of the given {@code entry}. */ 1229  E copyEntry(E original, E newNext) { 1230  return this.map.entryHelper.copy(self(), original, newNext); 1231  } 1232  1233  AtomicReferenceArray<E> newEntryArray(int size) { 1234  return new AtomicReferenceArray<E>(size); 1235  } 1236  1237  void initTable(AtomicReferenceArray<E> newTable) { 1238  this.threshold = newTable.length() * 3 / 4; // 0.75 1239  if (this.threshold == maxSegmentSize) { 1240  // prevent spurious expansion before eviction 1241  this.threshold++; 1242  } 1243  this.table = newTable; 1244  } 1245  1246  // Convenience methods for testing 1247  1248  /** 1249  * Unsafe cast of the given entry to {@code E}, the type of the specific {@link InternalEntry} 1250  * implementation type. 1251  * 1252  * <p>This method is provided as a convenience for tests. Otherwise they'd need to be 1253  * knowledgable about all the implementation details of our type system trickery. 1254  */ 1255  abstract E castForTesting(InternalEntry<K, V, ?> entry); 1256  1257  /** Unsafely extracts the key reference queue used by this segment. */ 1258  ReferenceQueue<K> getKeyReferenceQueueForTesting() { 1259  throw new AssertionError(); 1260  } 1261  1262  /** Unsafely extracts the value reference queue used by this segment. */ 1263  ReferenceQueue<V> getValueReferenceQueueForTesting() { 1264  throw new AssertionError(); 1265  } 1266  1267  /** Unsafely extracts the weak value reference inside of the given {@code entry}. */ 1268  WeakValueReference<K, V, E> getWeakValueReferenceForTesting(InternalEntry<K, V, ?> entry) { 1269  throw new AssertionError(); 1270  } 1271  1272  /** 1273  * Unsafely creates of a fresh {@link WeakValueReference}, referencing the given {@code value}, 1274  * for the given {@code entry} 1275  */ 1276  WeakValueReference<K, V, E> newWeakValueReferenceForTesting( 1277  InternalEntry<K, V, ?> entry, V value) { 1278  throw new AssertionError(); 1279  } 1280  1281  /** 1282  * Unsafely sets the weak value reference inside the given {@code entry} to be the given {@code 1283  * valueReference} 1284  */ 1285  void setWeakValueReferenceForTesting( 1286  InternalEntry<K, V, ?> entry, 1287  WeakValueReference<K, V, ? extends InternalEntry<K, V, ?>> valueReference) { 1288  throw new AssertionError(); 1289  } 1290  1291  /** 1292  * Unsafely sets the given index of this segment's internal hash table to be the given entry. 1293  */ 1294  void setTableEntryForTesting(int i, InternalEntry<K, V, ?> entry) { 1295  table.set(i, castForTesting(entry)); 1296  } 1297  1298  /** Unsafely returns a copy of the given entry. */ 1299  E copyForTesting(InternalEntry<K, V, ?> entry, @Nullable InternalEntry<K, V, ?> newNext) { 1300  return this.map.entryHelper.copy(self(), castForTesting(entry), castForTesting(newNext)); 1301  } 1302  1303  /** Unsafely sets the value of the given entry. */ 1304  void setValueForTesting(InternalEntry<K, V, ?> entry, V value) { 1305  this.map.entryHelper.setValue(self(), castForTesting(entry), value); 1306  } 1307  1308  /** Unsafely returns a fresh entry. */ 1309  E newEntryForTesting(K key, int hash, @Nullable InternalEntry<K, V, ?> next) { 1310  return this.map.entryHelper.newEntry(self(), key, hash, castForTesting(next)); 1311  } 1312  1313  /** Unsafely removes the given entry from this segment's hash table. */ 1314  @CanIgnoreReturnValue 1315  boolean removeTableEntryForTesting(InternalEntry<K, V, ?> entry) { 1316  return removeEntryForTesting(castForTesting(entry)); 1317  } 1318  1319  /** Unsafely removes the given entry from the given chain in this segment's hash table. */ 1320  E removeFromChainForTesting(InternalEntry<K, V, ?> first, InternalEntry<K, V, ?> entry) { 1321  return removeFromChain(castForTesting(first), castForTesting(entry)); 1322  } 1323  1324  /** 1325  * Unsafely returns the value of the given entry if it's still live, or {@code null} otherwise. 1326  */ 1327  @Nullable 1328  V getLiveValueForTesting(InternalEntry<K, V, ?> entry) { 1329  return getLiveValue(castForTesting(entry)); 1330  } 1331  1332  // reference queues, for garbage collection cleanup 1333  1334  /** Cleanup collected entries when the lock is available. */ 1335  void tryDrainReferenceQueues() { 1336  if (tryLock()) { 1337  try { 1338  maybeDrainReferenceQueues(); 1339  } finally { 1340  unlock(); 1341  } 1342  } 1343  } 1344  1345  @GuardedBy("this") 1346  void drainKeyReferenceQueue(ReferenceQueue<K> keyReferenceQueue) { 1347  Reference<? extends K> ref; 1348  int i = 0; 1349  while ((ref = keyReferenceQueue.poll()) != null) { 1350  @SuppressWarnings("unchecked") 1351  E entry = (E) ref; 1352  map.reclaimKey(entry); 1353  if (++i == DRAIN_MAX) { 1354  break; 1355  } 1356  } 1357  } 1358  1359  @GuardedBy("this") 1360  void drainValueReferenceQueue(ReferenceQueue<V> valueReferenceQueue) { 1361  Reference<? extends V> ref; 1362  int i = 0; 1363  while ((ref = valueReferenceQueue.poll()) != null) { 1364  @SuppressWarnings("unchecked") 1365  WeakValueReference<K, V, E> valueReference = (WeakValueReference<K, V, E>) ref; 1366  map.reclaimValue(valueReference); 1367  if (++i == DRAIN_MAX) { 1368  break; 1369  } 1370  } 1371  } 1372  1373  <T> void clearReferenceQueue(ReferenceQueue<T> referenceQueue) { 1374  while (referenceQueue.poll() != null) {} 1375  } 1376  1377  /** Returns first entry of bin for given hash. */ 1378  E getFirst(int hash) { 1379  // read this volatile field only once 1380  AtomicReferenceArray<E> table = this.table; 1381  return table.get(hash & (table.length() - 1)); 1382  } 1383  1384  // Specialized implementations of map methods 1385  1386  E getEntry(Object key, int hash) { 1387  if (count != 0) { // read-volatile 1388  for (E e = getFirst(hash); e != null; e = e.getNext()) { 1389  if (e.getHash() != hash) { 1390  continue; 1391  } 1392  1393  K entryKey = e.getKey(); 1394  if (entryKey == null) { 1395  tryDrainReferenceQueues(); 1396  continue; 1397  } 1398  1399  if (map.keyEquivalence.equivalent(key, entryKey)) { 1400  return e; 1401  } 1402  } 1403  } 1404  1405  return null; 1406  } 1407  1408  E getLiveEntry(Object key, int hash) { 1409  return getEntry(key, hash); 1410  } 1411  1412  V get(Object key, int hash) { 1413  try { 1414  E e = getLiveEntry(key, hash); 1415  if (e == null) { 1416  return null; 1417  } 1418  1419  V value = e.getValue(); 1420  if (value == null) { 1421  tryDrainReferenceQueues(); 1422  } 1423  return value; 1424  } finally { 1425  postReadCleanup(); 1426  } 1427  } 1428  1429  boolean containsKey(Object key, int hash) { 1430  try { 1431  if (count != 0) { // read-volatile 1432  E e = getLiveEntry(key, hash); 1433  return e != null && e.getValue() != null; 1434  } 1435  1436  return false; 1437  } finally { 1438  postReadCleanup(); 1439  } 1440  } 1441  1442  /** 1443  * This method is a convenience for testing. Code should call {@link 1444  * MapMakerInternalMap#containsValue} directly. 1445  */ 1446  @VisibleForTesting 1447  boolean containsValue(Object value) { 1448  try { 1449  if (count != 0) { // read-volatile 1450  AtomicReferenceArray<E> table = this.table; 1451  int length = table.length(); 1452  for (int i = 0; i < length; ++i) { 1453  for (E e = table.get(i); e != null; e = e.getNext()) { 1454  V entryValue = getLiveValue(e); 1455  if (entryValue == null) { 1456  continue; 1457  } 1458  if (map.valueEquivalence().equivalent(value, entryValue)) { 1459  return true; 1460  } 1461  } 1462  } 1463  } 1464  1465  return false; 1466  } finally { 1467  postReadCleanup(); 1468  } 1469  } 1470  1471  V put(K key, int hash, V value, boolean onlyIfAbsent) { 1472  lock(); 1473  try { 1474  preWriteCleanup(); 1475  1476  int newCount = this.count + 1; 1477  if (newCount > this.threshold) { // ensure capacity 1478  expand(); 1479  newCount = this.count + 1; 1480  } 1481  1482  AtomicReferenceArray<E> table = this.table; 1483  int index = hash & (table.length() - 1); 1484  E first = table.get(index); 1485  1486  // Look for an existing entry. 1487  for (E e = first; e != null; e = e.getNext()) { 1488  K entryKey = e.getKey(); 1489  if (e.getHash() == hash 1490  && entryKey != null 1491  && map.keyEquivalence.equivalent(key, entryKey)) { 1492  // We found an existing entry. 1493  1494  V entryValue = e.getValue(); 1495  1496  if (entryValue == null) { 1497  ++modCount; 1498  setValue(e, value); 1499  newCount = this.count; // count remains unchanged 1500  this.count = newCount; // write-volatile 1501  return null; 1502  } else if (onlyIfAbsent) { 1503  // Mimic 1504  // "if (!map.containsKey(key)) ... 1505  // else return map.get(key); 1506  return entryValue; 1507  } else { 1508  // clobber existing entry, count remains unchanged 1509  ++modCount; 1510  setValue(e, value); 1511  return entryValue; 1512  } 1513  } 1514  } 1515  1516  // Create a new entry. 1517  ++modCount; 1518  E newEntry = map.entryHelper.newEntry(self(), key, hash, first); 1519  setValue(newEntry, value); 1520  table.set(index, newEntry); 1521  this.count = newCount; // write-volatile 1522  return null; 1523  } finally { 1524  unlock(); 1525  } 1526  } 1527  1528  /** Expands the table if possible. */ 1529  @GuardedBy("this") 1530  void expand() { 1531  AtomicReferenceArray<E> oldTable = table; 1532  int oldCapacity = oldTable.length(); 1533  if (oldCapacity >= MAXIMUM_CAPACITY) { 1534  return; 1535  } 1536  1537  /* 1538  * Reclassify nodes in each list to new Map. Because we are using power-of-two expansion, the 1539  * elements from each bin must either stay at same index, or move with a power of two offset. 1540  * We eliminate unnecessary node creation by catching cases where old nodes can be reused 1541  * because their next fields won't change. Statistically, at the default threshold, only 1542  * about one-sixth of them need cloning when a table doubles. The nodes they replace will be 1543  * garbage collectable as soon as they are no longer referenced by any reader thread that may 1544  * be in the midst of traversing table right now. 1545  */ 1546  1547  int newCount = count; 1548  AtomicReferenceArray<E> newTable = newEntryArray(oldCapacity << 1); 1549  threshold = newTable.length() * 3 / 4; 1550  int newMask = newTable.length() - 1; 1551  for (int oldIndex = 0; oldIndex < oldCapacity; ++oldIndex) { 1552  // We need to guarantee that any existing reads of old Map can 1553  // proceed. So we cannot yet null out each bin. 1554  E head = oldTable.get(oldIndex); 1555  1556  if (head != null) { 1557  E next = head.getNext(); 1558  int headIndex = head.getHash() & newMask; 1559  1560  // Single node on list 1561  if (next == null) { 1562  newTable.set(headIndex, head); 1563  } else { 1564  // Reuse the consecutive sequence of nodes with the same target 1565  // index from the end of the list. tail points to the first 1566  // entry in the reusable list. 1567  E tail = head; 1568  int tailIndex = headIndex; 1569  for (E e = next; e != null; e = e.getNext()) { 1570  int newIndex = e.getHash() & newMask; 1571  if (newIndex != tailIndex) { 1572  // The index changed. We'll need to copy the previous entry. 1573  tailIndex = newIndex; 1574  tail = e; 1575  } 1576  } 1577  newTable.set(tailIndex, tail); 1578  1579  // Clone nodes leading up to the tail. 1580  for (E e = head; e != tail; e = e.getNext()) { 1581  int newIndex = e.getHash() & newMask; 1582  E newNext = newTable.get(newIndex); 1583  E newFirst = copyEntry(e, newNext); 1584  if (newFirst != null) { 1585  newTable.set(newIndex, newFirst); 1586  } else { 1587  newCount--; 1588  } 1589  } 1590  } 1591  } 1592  } 1593  table = newTable; 1594  this.count = newCount; 1595  } 1596  1597  boolean replace(K key, int hash, V oldValue, V newValue) { 1598  lock(); 1599  try { 1600  preWriteCleanup(); 1601  1602  AtomicReferenceArray<E> table = this.table; 1603  int index = hash & (table.length() - 1); 1604  E first = table.get(index); 1605  1606  for (E e = first; e != null; e = e.getNext()) { 1607  K entryKey = e.getKey(); 1608  if (e.getHash() == hash 1609  && entryKey != null 1610  && map.keyEquivalence.equivalent(key, entryKey)) { 1611  // If the value disappeared, this entry is partially collected, 1612  // and we should pretend like it doesn't exist. 1613  V entryValue = e.getValue(); 1614  if (entryValue == null) { 1615  if (isCollected(e)) { 1616  int newCount = this.count - 1; 1617  ++modCount; 1618  E newFirst = removeFromChain(first, e); 1619  newCount = this.count - 1; 1620  table.set(index, newFirst); 1621  this.count = newCount; // write-volatile 1622  } 1623  return false; 1624  } 1625  1626  if (map.valueEquivalence().equivalent(oldValue, entryValue)) { 1627  ++modCount; 1628  setValue(e, newValue); 1629  return true; 1630  } else { 1631  // Mimic 1632  // "if (map.containsKey(key) && map.get(key).equals(oldValue))..." 1633  return false; 1634  } 1635  } 1636  } 1637  1638  return false; 1639  } finally { 1640  unlock(); 1641  } 1642  } 1643  1644  V replace(K key, int hash, V newValue) { 1645  lock(); 1646  try { 1647  preWriteCleanup(); 1648  1649  AtomicReferenceArray<E> table = this.table; 1650  int index = hash & (table.length() - 1); 1651  E first = table.get(index); 1652  1653  for (E e = first; e != null; e = e.getNext()) { 1654  K entryKey = e.getKey(); 1655  if (e.getHash() == hash 1656  && entryKey != null 1657  && map.keyEquivalence.equivalent(key, entryKey)) { 1658  // If the value disappeared, this entry is partially collected, 1659  // and we should pretend like it doesn't exist. 1660  V entryValue = e.getValue(); 1661  if (entryValue == null) { 1662  if (isCollected(e)) { 1663  int newCount = this.count - 1; 1664  ++modCount; 1665  E newFirst = removeFromChain(first, e); 1666  newCount = this.count - 1; 1667  table.set(index, newFirst); 1668  this.count = newCount; // write-volatile 1669  } 1670  return null; 1671  } 1672  1673  ++modCount; 1674  setValue(e, newValue); 1675  return entryValue; 1676  } 1677  } 1678  1679  return null; 1680  } finally { 1681  unlock(); 1682  } 1683  } 1684  1685  @CanIgnoreReturnValue 1686  V remove(Object key, int hash) { 1687  lock(); 1688  try { 1689  preWriteCleanup(); 1690  1691  int newCount = this.count - 1; 1692  AtomicReferenceArray<E> table = this.table; 1693  int index = hash & (table.length() - 1); 1694  E first = table.get(index); 1695  1696  for (E e = first; e != null; e = e.getNext()) { 1697  K entryKey = e.getKey(); 1698  if (e.getHash() == hash 1699  && entryKey != null 1700  && map.keyEquivalence.equivalent(key, entryKey)) { 1701  V entryValue = e.getValue(); 1702  1703  if (entryValue != null) { 1704  // TODO(kak): Remove this branch 1705  } else if (isCollected(e)) { 1706  // TODO(kak): Remove this branch 1707  } else { 1708  return null; 1709  } 1710  1711  ++modCount; 1712  E newFirst = removeFromChain(first, e); 1713  newCount = this.count - 1; 1714  table.set(index, newFirst); 1715  this.count = newCount; // write-volatile 1716  return entryValue; 1717  } 1718  } 1719  1720  return null; 1721  } finally { 1722  unlock(); 1723  } 1724  } 1725  1726  boolean remove(Object key, int hash, Object value) { 1727  lock(); 1728  try { 1729  preWriteCleanup(); 1730  1731  int newCount = this.count - 1; 1732  AtomicReferenceArray<E> table = this.table; 1733  int index = hash & (table.length() - 1); 1734  E first = table.get(index); 1735  1736  for (E e = first; e != null; e = e.getNext()) { 1737  K entryKey = e.getKey(); 1738  if (e.getHash() == hash 1739  && entryKey != null 1740  && map.keyEquivalence.equivalent(key, entryKey)) { 1741  V entryValue = e.getValue(); 1742  1743  boolean explicitRemoval = false; 1744  if (map.valueEquivalence().equivalent(value, entryValue)) { 1745  explicitRemoval = true; 1746  } else if (isCollected(e)) { 1747  // TODO(kak): Remove this branch 1748  } else { 1749  return false; 1750  } 1751  1752  ++modCount; 1753  E newFirst = removeFromChain(first, e); 1754  newCount = this.count - 1; 1755  table.set(index, newFirst); 1756  this.count = newCount; // write-volatile 1757  return explicitRemoval; 1758  } 1759  } 1760  1761  return false; 1762  } finally { 1763  unlock(); 1764  } 1765  } 1766  1767  void clear() { 1768  if (count != 0) { 1769  lock(); 1770  try { 1771  AtomicReferenceArray<E> table = this.table; 1772  for (int i = 0; i < table.length(); ++i) { 1773  table.set(i, null); 1774  } 1775  maybeClearReferenceQueues(); 1776  readCount.set(0); 1777  1778  ++modCount; 1779  count = 0; // write-volatile 1780  } finally { 1781  unlock(); 1782  } 1783  } 1784  } 1785  1786  /** 1787  * Removes an entry from within a table. All entries following the removed node can stay, but 1788  * all preceding ones need to be cloned. 1789  * 1790  * <p>This method does not decrement count for the removed entry, but does decrement count for 1791  * all partially collected entries which are skipped. As such callers which are modifying count 1792  * must re-read it after calling removeFromChain. 1793  * 1794  * @param first the first entry of the table 1795  * @param entry the entry being removed from the table 1796  * @return the new first entry for the table 1797  */ 1798  @GuardedBy("this") 1799  E removeFromChain(E first, E entry) { 1800  int newCount = count; 1801  E newFirst = entry.getNext(); 1802  for (E e = first; e != entry; e = e.getNext()) { 1803  E next = copyEntry(e, newFirst); 1804  if (next != null) { 1805  newFirst = next; 1806  } else { 1807  newCount--; 1808  } 1809  } 1810  this.count = newCount; 1811  return newFirst; 1812  } 1813  1814  /** Removes an entry whose key has been garbage collected. */ 1815  @CanIgnoreReturnValue 1816  boolean reclaimKey(E entry, int hash) { 1817  lock(); 1818  try { 1819  int newCount = count - 1; 1820  AtomicReferenceArray<E> table = this.table; 1821  int index = hash & (table.length() - 1); 1822  E first = table.get(index); 1823  1824  for (E e = first; e != null; e = e.getNext()) { 1825  if (e == entry) { 1826  ++modCount; 1827  E newFirst = removeFromChain(first, e); 1828  newCount = this.count - 1; 1829  table.set(index, newFirst); 1830  this.count = newCount; // write-volatile 1831  return true; 1832  } 1833  } 1834  1835  return false; 1836  } finally { 1837  unlock(); 1838  } 1839  } 1840  1841  /** Removes an entry whose value has been garbage collected. */ 1842  @CanIgnoreReturnValue 1843  boolean reclaimValue(K key, int hash, WeakValueReference<K, V, E> valueReference) { 1844  lock(); 1845  try { 1846  int newCount = this.count - 1; 1847  AtomicReferenceArray<E> table = this.table; 1848  int index = hash & (table.length() - 1); 1849  E first = table.get(index); 1850  1851  for (E e = first; e != null; e = e.getNext()) { 1852  K entryKey = e.getKey(); 1853  if (e.getHash() == hash 1854  && entryKey != null 1855  && map.keyEquivalence.equivalent(key, entryKey)) { 1856  WeakValueReference<K, V, E> v = ((WeakValueEntry<K, V, E>) e).getValueReference(); 1857  if (v == valueReference) { 1858  ++modCount; 1859  E newFirst = removeFromChain(first, e); 1860  newCount = this.count - 1; 1861  table.set(index, newFirst); 1862  this.count = newCount; // write-volatile 1863  return true; 1864  } 1865  return false; 1866  } 1867  } 1868  1869  return false; 1870  } finally { 1871  unlock(); 1872  } 1873  } 1874  1875  /** Clears a value that has not yet been set, and thus does not require count to be modified. */ 1876  @CanIgnoreReturnValue 1877  boolean clearValueForTesting( 1878  K key, 1879  int hash, 1880  WeakValueReference<K, V, ? extends InternalEntry<K, V, ?>> valueReference) { 1881  lock(); 1882  try { 1883  AtomicReferenceArray<E> table = this.table; 1884  int index = hash & (table.length() - 1); 1885  E first = table.get(index); 1886  1887  for (E e = first; e != null; e = e.getNext()) { 1888  K entryKey = e.getKey(); 1889  if (e.getHash() == hash 1890  && entryKey != null 1891  && map.keyEquivalence.equivalent(key, entryKey)) { 1892  WeakValueReference<K, V, E> v = ((WeakValueEntry<K, V, E>) e).getValueReference(); 1893  if (v == valueReference) { 1894  E newFirst = removeFromChain(first, e); 1895  table.set(index, newFirst); 1896  return true; 1897  } 1898  return false; 1899  } 1900  } 1901  1902  return false; 1903  } finally { 1904  unlock(); 1905  } 1906  } 1907  1908  @GuardedBy("this") 1909  boolean removeEntryForTesting(E entry) { 1910  int hash = entry.getHash(); 1911  int newCount = this.count - 1; 1912  AtomicReferenceArray<E> table = this.table; 1913  int index = hash & (table.length() - 1); 1914  E first = table.get(index); 1915  1916  for (E e = first; e != null; e = e.getNext()) { 1917  if (e == entry) { 1918  ++modCount; 1919  E newFirst = removeFromChain(first, e); 1920  newCount = this.count - 1; 1921  table.set(index, newFirst); 1922  this.count = newCount; // write-volatile 1923  return true; 1924  } 1925  } 1926  1927  return false; 1928  } 1929  1930  /** 1931  * Returns {@code true} if the value has been partially collected, meaning that the value is 1932  * null. 1933  */ 1934  static <K, V, E extends InternalEntry<K, V, E>> boolean isCollected(E entry) { 1935  return entry.getValue() == null; 1936  } 1937  1938  /** 1939  * Gets the value from an entry. Returns {@code null} if the entry is invalid or 1940  * partially-collected. 1941  */ 1942  @Nullable 1943  V getLiveValue(E entry) { 1944  if (entry.getKey() == null) { 1945  tryDrainReferenceQueues(); 1946  return null; 1947  } 1948  V value = entry.getValue(); 1949  if (value == null) { 1950  tryDrainReferenceQueues(); 1951  return null; 1952  } 1953  1954  return value; 1955  } 1956  1957  /** 1958  * Performs routine cleanup following a read. Normally cleanup happens during writes, or from 1959  * the cleanupExecutor. If cleanup is not observed after a sufficient number of reads, try 1960  * cleaning up from the read thread. 1961  */ 1962  void postReadCleanup() { 1963  if ((readCount.incrementAndGet() & DRAIN_THRESHOLD) == 0) { 1964  runCleanup(); 1965  } 1966  } 1967  1968  /** 1969  * Performs routine cleanup prior to executing a write. This should be called every time a write 1970  * thread acquires the segment lock, immediately after acquiring the lock. 1971  */ 1972  @GuardedBy("this") 1973  void preWriteCleanup() { 1974  runLockedCleanup(); 1975  } 1976  1977  void runCleanup() { 1978  runLockedCleanup(); 1979  } 1980  1981  void runLockedCleanup() { 1982  if (tryLock()) { 1983  try { 1984  maybeDrainReferenceQueues(); 1985  readCount.set(0); 1986  } finally { 1987  unlock(); 1988  } 1989  } 1990  } 1991  } 1992  1993  /** Concrete implementation of {@link Segment} for strong keys and strong values. */ 1994  static final class StrongKeyStrongValueSegment<K, V> 1995  extends Segment<K, V, StrongKeyStrongValueEntry<K, V>, StrongKeyStrongValueSegment<K, V>> { 1996  StrongKeyStrongValueSegment( 1997  MapMakerInternalMap< 1998  K, V, StrongKeyStrongValueEntry<K, V>, StrongKeyStrongValueSegment<K, V>> 1999  map, 2000  int initialCapacity, 2001  int maxSegmentSize) { 2002  super(map, initialCapacity, maxSegmentSize); 2003  } 2004  2005  @Override 2006  StrongKeyStrongValueSegment<K, V> self() { 2007  return this; 2008  } 2009  2010  @SuppressWarnings("unchecked") 2011  @Override 2012  public StrongKeyStrongValueEntry<K, V> castForTesting(InternalEntry<K, V, ?> entry) { 2013  return (StrongKeyStrongValueEntry<K, V>) entry; 2014  } 2015  } 2016  2017  /** Concrete implementation of {@link Segment} for strong keys and weak values. */ 2018  static final class StrongKeyWeakValueSegment<K, V> 2019  extends Segment<K, V, StrongKeyWeakValueEntry<K, V>, StrongKeyWeakValueSegment<K, V>> { 2020  private final ReferenceQueue<V> queueForValues = new ReferenceQueue<V>(); 2021  2022  StrongKeyWeakValueSegment( 2023  MapMakerInternalMap<K, V, StrongKeyWeakValueEntry<K, V>, StrongKeyWeakValueSegment<K, V>> 2024  map, 2025  int initialCapacity, 2026  int maxSegmentSize) { 2027  super(map, initialCapacity, maxSegmentSize); 2028  } 2029  2030  @Override 2031  StrongKeyWeakValueSegment<K, V> self() { 2032  return this; 2033  } 2034  2035  @Override 2036  ReferenceQueue<V> getValueReferenceQueueForTesting() { 2037  return queueForValues; 2038  } 2039  2040  @SuppressWarnings("unchecked") 2041  @Override 2042  public StrongKeyWeakValueEntry<K, V> castForTesting(InternalEntry<K, V, ?> entry) { 2043  return (StrongKeyWeakValueEntry<K, V>) entry; 2044  } 2045  2046  @Override 2047  public WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> getWeakValueReferenceForTesting( 2048  InternalEntry<K, V, ?> e) { 2049  return castForTesting(e).getValueReference(); 2050  } 2051  2052  @Override 2053  public WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> newWeakValueReferenceForTesting( 2054  InternalEntry<K, V, ?> e, V value) { 2055  return new WeakValueReferenceImpl<>(queueForValues, value, castForTesting(e)); 2056  } 2057  2058  @Override 2059  public void setWeakValueReferenceForTesting( 2060  InternalEntry<K, V, ?> e, 2061  WeakValueReference<K, V, ? extends InternalEntry<K, V, ?>> valueReference) { 2062  StrongKeyWeakValueEntry<K, V> entry = castForTesting(e); 2063  @SuppressWarnings("unchecked") 2064  WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> newValueReference = 2065  (WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>>) valueReference; 2066  WeakValueReference<K, V, StrongKeyWeakValueEntry<K, V>> previous = entry.valueReference; 2067  entry.valueReference = newValueReference; 2068  previous.clear(); 2069  } 2070  2071  @Override 2072  void maybeDrainReferenceQueues() { 2073  drainValueReferenceQueue(queueForValues); 2074  } 2075  2076  @Override 2077  void maybeClearReferenceQueues() { 2078  clearReferenceQueue(queueForValues); 2079  } 2080  } 2081  2082  /** Concrete implementation of {@link Segment} for strong keys and {@link Dummy} values. */ 2083  static final class StrongKeyDummyValueSegment<K> 2084  extends Segment<K, Dummy, StrongKeyDummyValueEntry<K>, StrongKeyDummyValueSegment<K>> { 2085  StrongKeyDummyValueSegment( 2086  MapMakerInternalMap<K, Dummy, StrongKeyDummyValueEntry<K>, StrongKeyDummyValueSegment<K>> 2087  map, 2088  int initialCapacity, 2089  int maxSegmentSize) { 2090  super(map, initialCapacity, maxSegmentSize); 2091  } 2092  2093  @Override 2094  StrongKeyDummyValueSegment<K> self() { 2095  return this; 2096  } 2097  2098  @SuppressWarnings("unchecked") 2099  @Override 2100  public StrongKeyDummyValueEntry<K> castForTesting(InternalEntry<K, Dummy, ?> entry) { 2101  return (StrongKeyDummyValueEntry<K>) entry; 2102  } 2103  } 2104  2105  /** Concrete implementation of {@link Segment} for weak keys and strong values. */ 2106  static final class WeakKeyStrongValueSegment<K, V> 2107  extends Segment<K, V, WeakKeyStrongValueEntry<K, V>, WeakKeyStrongValueSegment<K, V>> { 2108  private final ReferenceQueue<K> queueForKeys = new ReferenceQueue<K>(); 2109  2110  WeakKeyStrongValueSegment( 2111  MapMakerInternalMap<K, V, WeakKeyStrongValueEntry<K, V>, WeakKeyStrongValueSegment<K, V>> 2112  map, 2113  int initialCapacity, 2114  int maxSegmentSize) { 2115  super(map, initialCapacity, maxSegmentSize); 2116  } 2117  2118  @Override 2119  WeakKeyStrongValueSegment<K, V> self() { 2120  return this; 2121  } 2122  2123  @Override 2124  ReferenceQueue<K> getKeyReferenceQueueForTesting() { 2125  return queueForKeys; 2126  } 2127  2128  @SuppressWarnings("unchecked") 2129  @Override 2130  public WeakKeyStrongValueEntry<K, V> castForTesting(InternalEntry<K, V, ?> entry) { 2131  return (WeakKeyStrongValueEntry<K, V>) entry; 2132  } 2133  2134  @Override 2135  void maybeDrainReferenceQueues() { 2136  drainKeyReferenceQueue(queueForKeys); 2137  } 2138  2139  @Override 2140  void maybeClearReferenceQueues() { 2141  clearReferenceQueue(queueForKeys); 2142  } 2143  } 2144  2145  /** Concrete implementation of {@link Segment} for weak keys and weak values. */ 2146  static final class WeakKeyWeakValueSegment<K, V> 2147  extends Segment<K, V, WeakKeyWeakValueEntry<K, V>, WeakKeyWeakValueSegment<K, V>> { 2148  private final ReferenceQueue<K> queueForKeys = new ReferenceQueue<K>(); 2149  private final ReferenceQueue<V> queueForValues = new ReferenceQueue<V>(); 2150  2151  WeakKeyWeakValueSegment( 2152  MapMakerInternalMap<K, V, WeakKeyWeakValueEntry<K, V>, WeakKeyWeakValueSegment<K, V>> map, 2153  int initialCapacity, 2154  int maxSegmentSize) { 2155  super(map, initialCapacity, maxSegmentSize); 2156  } 2157  2158  @Override 2159  WeakKeyWeakValueSegment<K, V> self() { 2160  return this; 2161  } 2162  2163  @Override 2164  ReferenceQueue<K> getKeyReferenceQueueForTesting() { 2165  return queueForKeys; 2166  } 2167  2168  @Override 2169  ReferenceQueue<V> getValueReferenceQueueForTesting() { 2170  return queueForValues; 2171  } 2172  2173  @SuppressWarnings("unchecked") 2174  @Override 2175  public WeakKeyWeakValueEntry<K, V> castForTesting(InternalEntry<K, V, ?> entry) { 2176  return (WeakKeyWeakValueEntry<K, V>) entry; 2177  } 2178  2179  @Override 2180  public WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> getWeakValueReferenceForTesting( 2181  InternalEntry<K, V, ?> e) { 2182  return castForTesting(e).getValueReference(); 2183  } 2184  2185  @Override 2186  public WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> newWeakValueReferenceForTesting( 2187  InternalEntry<K, V, ?> e, V value) { 2188  return new WeakValueReferenceImpl<>(queueForValues, value, castForTesting(e)); 2189  } 2190  2191  @Override 2192  public void setWeakValueReferenceForTesting( 2193  InternalEntry<K, V, ?> e, 2194  WeakValueReference<K, V, ? extends InternalEntry<K, V, ?>> valueReference) { 2195  WeakKeyWeakValueEntry<K, V> entry = castForTesting(e); 2196  @SuppressWarnings("unchecked") 2197  WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> newValueReference = 2198  (WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>>) valueReference; 2199  WeakValueReference<K, V, WeakKeyWeakValueEntry<K, V>> previous = entry.valueReference; 2200  entry.valueReference = newValueReference; 2201  previous.clear(); 2202  } 2203  2204  @Override 2205  void maybeDrainReferenceQueues() { 2206  drainKeyReferenceQueue(queueForKeys); 2207  drainValueReferenceQueue(queueForValues); 2208  } 2209  2210  @Override 2211  void maybeClearReferenceQueues() { 2212  clearReferenceQueue(queueForKeys); 2213  } 2214  } 2215  2216  /** Concrete implementation of {@link Segment} for weak keys and {@link Dummy} values. */ 2217  static final class WeakKeyDummyValueSegment<K> 2218  extends Segment<K, Dummy, WeakKeyDummyValueEntry<K>, WeakKeyDummyValueSegment<K>> { 2219  private final ReferenceQueue<K> queueForKeys = new ReferenceQueue<K>(); 2220  2221  WeakKeyDummyValueSegment( 2222  MapMakerInternalMap<K, Dummy, WeakKeyDummyValueEntry<K>, WeakKeyDummyValueSegment<K>> map, 2223  int initialCapacity, 2224  int maxSegmentSize) { 2225  super(map, initialCapacity, maxSegmentSize); 2226  } 2227  2228  @Override 2229  WeakKeyDummyValueSegment<K> self() { 2230  return this; 2231  } 2232  2233  @Override 2234  ReferenceQueue<K> getKeyReferenceQueueForTesting() { 2235  return queueForKeys; 2236  } 2237  2238  @SuppressWarnings("unchecked") 2239  @Override 2240  public WeakKeyDummyValueEntry<K> castForTesting(InternalEntry<K, Dummy, ?> entry) { 2241  return (WeakKeyDummyValueEntry<K>) entry; 2242  } 2243  2244  @Override 2245  void maybeDrainReferenceQueues() { 2246  drainKeyReferenceQueue(queueForKeys); 2247  } 2248  2249  @Override 2250  void maybeClearReferenceQueues() { 2251  clearReferenceQueue(queueForKeys); 2252  } 2253  } 2254  2255  static final class CleanupMapTask implements Runnable { 2256  final WeakReference<MapMakerInternalMap<?, ?, ?, ?>> mapReference; 2257  2258  public CleanupMapTask(MapMakerInternalMap<?, ?, ?, ?> map) { 2259  this.mapReference = new WeakReference<MapMakerInternalMap<?, ?, ?, ?>>(map); 2260  } 2261  2262  @Override 2263  public void run() { 2264  MapMakerInternalMap<?, ?, ?, ?> map = mapReference.get(); 2265  if (map == null) { 2266  throw new CancellationException(); 2267  } 2268  2269  for (Segment<?, ?, ?, ?> segment : map.segments) { 2270  segment.runCleanup(); 2271  } 2272  } 2273  } 2274  2275  @VisibleForTesting 2276  Strength keyStrength() { 2277  return entryHelper.keyStrength(); 2278  } 2279  2280  @VisibleForTesting 2281  Strength valueStrength() { 2282  return entryHelper.valueStrength(); 2283  } 2284  2285  @VisibleForTesting 2286  Equivalence<Object> valueEquivalence() { 2287  return entryHelper.valueStrength().defaultEquivalence(); 2288  } 2289  2290  // ConcurrentMap methods 2291  2292  @Override 2293  public boolean isEmpty() { 2294  /* 2295  * Sum per-segment modCounts to avoid mis-reporting when elements are concurrently added and 2296  * removed in one segment while checking another, in which case the table was never actually 2297  * empty at any point. (The sum ensures accuracy up through at least 1<<31 per-segment 2298  * modifications before recheck.) Method containsValue() uses similar constructions for 2299  * stability checks. 2300  */ 2301  long sum = 0L; 2302  Segment<K, V, E, S>[] segments = this.segments; 2303  for (int i = 0; i < segments.length; ++i) { 2304  if (segments[i].count != 0) { 2305  return false; 2306  } 2307  sum += segments[i].modCount; 2308  } 2309  2310  if (sum != 0L) { // recheck unless no modifications 2311  for (int i = 0; i < segments.length; ++i) { 2312  if (segments[i].count != 0) { 2313  return false; 2314  } 2315  sum -= segments[i].modCount; 2316  } 2317  return sum == 0L; 2318  } 2319  return true; 2320  } 2321  2322  @Override 2323  public int size() { 2324  Segment<K, V, E, S>[] segments = this.segments; 2325  long sum = 0; 2326  for (int i = 0; i < segments.length; ++i) { 2327  sum += segments[i].count; 2328  } 2329  return Ints.saturatedCast(sum); 2330  } 2331  2332  @Override 2333  public V get(@Nullable Object key) { 2334  if (key == null) { 2335  return null; 2336  } 2337  int hash = hash(key); 2338  return segmentFor(hash).get(key, hash); 2339  } 2340  2341  /** 2342  * Returns the internal entry for the specified key. The entry may be computing or partially 2343  * collected. Does not impact recency ordering. 2344  */ 2345  E getEntry(@Nullable Object key) { 2346  if (key == null) { 2347  return null; 2348  } 2349  int hash = hash(key); 2350  return segmentFor(hash).getEntry(key, hash); 2351  } 2352  2353  @Override 2354  public boolean containsKey(@Nullable Object key) { 2355  if (key == null) { 2356  return false; 2357  } 2358  int hash = hash(key); 2359  return segmentFor(hash).containsKey(key, hash); 2360  } 2361  2362  @Override 2363  public boolean containsValue(@Nullable Object value) { 2364  if (value == null) { 2365  return false; 2366  } 2367  2368  // This implementation is patterned after ConcurrentHashMap, but without the locking. The only 2369  // way for it to return a false negative would be for the target value to jump around in the map 2370  // such that none of the subsequent iterations observed it, despite the fact that at every point 2371  // in time it was present somewhere int the map. This becomes increasingly unlikely as 2372  // CONTAINS_VALUE_RETRIES increases, though without locking it is theoretically possible. 2373  final Segment<K, V, E, S>[] segments = this.segments; 2374  long last = -1L; 2375  for (int i = 0; i < CONTAINS_VALUE_RETRIES; i++) { 2376  long sum = 0L; 2377  for (Segment<K, V, E, S> segment : segments) { 2378  // ensure visibility of most recent completed write 2379  int unused = segment.count; // read-volatile 2380  2381  AtomicReferenceArray<E> table = segment.table; 2382  for (int j = 0; j < table.length(); j++) { 2383  for (E e = table.get(j); e != null; e = e.getNext()) { 2384  V v = segment.getLiveValue(e); 2385  if (v != null && valueEquivalence().equivalent(value, v)) { 2386  return true; 2387  } 2388  } 2389  } 2390  sum += segment.modCount; 2391  } 2392  if (sum == last) { 2393  break; 2394  } 2395  last = sum; 2396  } 2397  return false; 2398  } 2399  2400  @CanIgnoreReturnValue 2401  @Override 2402  public V put(K key, V value) { 2403  checkNotNull(key); 2404  checkNotNull(value); 2405  int hash = hash(key); 2406  return segmentFor(hash).put(key, hash, value, false); 2407  } 2408  2409  @CanIgnoreReturnValue 2410  @Override 2411  public V putIfAbsent(K key, V value) { 2412  checkNotNull(key); 2413  checkNotNull(value); 2414  int hash = hash(key); 2415  return segmentFor(hash).put(key, hash, value, true); 2416  } 2417  2418  @Override 2419  public void putAll(Map<? extends K, ? extends V> m) { 2420  for (Entry<? extends K, ? extends V> e : m.entrySet()) { 2421  put(e.getKey(), e.getValue()); 2422  } 2423  } 2424  2425  @CanIgnoreReturnValue 2426  @Override 2427  public V remove(@Nullable Object key) { 2428  if (key == null) { 2429  return null; 2430  } 2431  int hash = hash(key); 2432  return segmentFor(hash).remove(key, hash); 2433  } 2434  2435  @CanIgnoreReturnValue 2436  @Override 2437  public boolean remove(@Nullable Object key, @Nullable Object value) { 2438  if (key == null || value == null) { 2439  return false; 2440  } 2441  int hash = hash(key); 2442  return segmentFor(hash).remove(key, hash, value); 2443  } 2444  2445  @CanIgnoreReturnValue 2446  @Override 2447  public boolean replace(K key, @Nullable V oldValue, V newValue) { 2448  checkNotNull(key); 2449  checkNotNull(newValue); 2450  if (oldValue == null) { 2451  return false; 2452  } 2453  int hash = hash(key); 2454  return segmentFor(hash).replace(key, hash, oldValue, newValue); 2455  } 2456  2457  @CanIgnoreReturnValue 2458  @Override 2459  public V replace(K key, V value) { 2460  checkNotNull(key); 2461  checkNotNull(value); 2462  int hash = hash(key); 2463  return segmentFor(hash).replace(key, hash, value); 2464  } 2465  2466  @Override 2467  public void clear() { 2468  for (Segment<K, V, E, S> segment : segments) { 2469  segment.clear(); 2470  } 2471  } 2472  2473  transient @Nullable Set<K> keySet; 2474  2475  @Override 2476  public Set<K> keySet() { 2477  Set<K> ks = keySet; 2478  return (ks != null) ? ks : (keySet = new KeySet()); 2479  } 2480  2481  transient @Nullable Collection<V> values; 2482  2483  @Override 2484  public Collection<V> values() { 2485  Collection<V> vs = values; 2486  return (vs != null) ? vs : (values = new Values()); 2487  } 2488  2489  transient @Nullable Set<Entry<K, V>> entrySet; 2490  2491  @Override 2492  public Set<Entry<K, V>> entrySet() { 2493  Set<Entry<K, V>> es = entrySet; 2494  return (es != null) ? es : (entrySet = new EntrySet()); 2495  } 2496  2497  // Iterator Support 2498  2499  abstract class HashIterator<T> implements Iterator<T> { 2500  2501  int nextSegmentIndex; 2502  int nextTableIndex; 2503  @Nullable Segment<K, V, E, S> currentSegment; 2504  @Nullable AtomicReferenceArray<E> currentTable; 2505  @Nullable E nextEntry; 2506  @Nullable WriteThroughEntry nextExternal; 2507  @Nullable WriteThroughEntry lastReturned; 2508  2509  HashIterator() { 2510  nextSegmentIndex = segments.length - 1; 2511  nextTableIndex = -1; 2512  advance(); 2513  } 2514  2515  @Override 2516  public abstract T next(); 2517  2518  final void advance() { 2519  nextExternal = null; 2520  2521  if (nextInChain()) { 2522  return; 2523  } 2524  2525  if (nextInTable()) { 2526  return; 2527  } 2528  2529  while (nextSegmentIndex >= 0) { 2530  currentSegment = segments[nextSegmentIndex--]; 2531  if (currentSegment.count != 0) { 2532  currentTable = currentSegment.table; 2533  nextTableIndex = currentTable.length() - 1; 2534  if (nextInTable()) { 2535  return; 2536  } 2537  } 2538  } 2539  } 2540  2541  /** Finds the next entry in the current chain. Returns {@code true} if an entry was found. */ 2542  boolean nextInChain() { 2543  if (nextEntry != null) { 2544  for (nextEntry = nextEntry.getNext(); nextEntry != null; nextEntry = nextEntry.getNext()) { 2545  if (advanceTo(nextEntry)) { 2546  return true; 2547  } 2548  } 2549  } 2550  return false; 2551  } 2552  2553  /** Finds the next entry in the current table. Returns {@code true} if an entry was found. */ 2554  boolean nextInTable() { 2555  while (nextTableIndex >= 0) { 2556  if ((nextEntry = currentTable.get(nextTableIndex--)) != null) { 2557  if (advanceTo(nextEntry) || nextInChain()) { 2558  return true; 2559  } 2560  } 2561  } 2562  return false; 2563  } 2564  2565  /** 2566  * Advances to the given entry. Returns {@code true} if the entry was valid, {@code false} if it 2567  * should be skipped. 2568  */ 2569  boolean advanceTo(E entry) { 2570  try { 2571  K key = entry.getKey(); 2572  V value = getLiveValue(entry); 2573  if (value != null) { 2574  nextExternal = new WriteThroughEntry(key, value); 2575  return true; 2576  } else { 2577  // Skip stale entry. 2578  return false; 2579  } 2580  } finally { 2581  currentSegment.postReadCleanup(); 2582  } 2583  } 2584  2585  @Override 2586  public boolean hasNext() { 2587  return nextExternal != null; 2588  } 2589  2590  WriteThroughEntry nextEntry() { 2591  if (nextExternal == null) { 2592  throw new NoSuchElementException(); 2593  } 2594  lastReturned = nextExternal; 2595  advance(); 2596  return lastReturned; 2597  } 2598  2599  @Override 2600  public void remove() { 2601  checkRemove(lastReturned != null); 2602  MapMakerInternalMap.this.remove(lastReturned.getKey()); 2603  lastReturned = null; 2604  } 2605  } 2606  2607  final class KeyIterator extends HashIterator<K> { 2608  2609  @Override 2610  public K next() { 2611  return nextEntry().getKey(); 2612  } 2613  } 2614  2615  final class ValueIterator extends HashIterator<V> { 2616  2617  @Override 2618  public V next() { 2619  return nextEntry().getValue(); 2620  } 2621  } 2622  2623  /** 2624  * Custom Entry class used by EntryIterator.next(), that relays setValue changes to the underlying 2625  * map. 2626  */ 2627  final class WriteThroughEntry extends AbstractMapEntry<K, V> { 2628  final K key; // non-null 2629  V value; // non-null 2630  2631  WriteThroughEntry(K key, V value) { 2632  this.key = key; 2633  this.value = value; 2634  } 2635  2636  @Override 2637  public K getKey() { 2638  return key; 2639  } 2640  2641  @Override 2642  public V getValue() { 2643  return value; 2644  } 2645  2646  @Override 2647  public boolean equals(@Nullable Object object) { 2648  // Cannot use key and value equivalence 2649  if (object instanceof Entry) { 2650  Entry<?, ?> that = (Entry<?, ?>) object; 2651  return key.equals(that.getKey()) && value.equals(that.getValue()); 2652  } 2653  return false; 2654  } 2655  2656  @Override 2657  public int hashCode() { 2658  // Cannot use key and value equivalence 2659  return key.hashCode() ^ value.hashCode(); 2660  } 2661  2662  @Override 2663  public V setValue(V newValue) { 2664  V oldValue = put(key, newValue); 2665  value = newValue; // only if put succeeds 2666  return oldValue; 2667  } 2668  } 2669  2670  final class EntryIterator extends HashIterator<Entry<K, V>> { 2671  2672  @Override 2673  public Entry<K, V> next() { 2674  return nextEntry(); 2675  } 2676  } 2677  2678  @WeakOuter 2679  final class KeySet extends SafeToArraySet<K> { 2680  2681  @Override 2682  public Iterator<K> iterator() { 2683  return new KeyIterator(); 2684  } 2685  2686  @Override 2687  public int size() { 2688  return MapMakerInternalMap.this.size(); 2689  } 2690  2691  @Override 2692  public boolean isEmpty() { 2693  return MapMakerInternalMap.this.isEmpty(); 2694  } 2695  2696  @Override 2697  public boolean contains(Object o) { 2698  return MapMakerInternalMap.this.containsKey(o); 2699  } 2700  2701  @Override 2702  public boolean remove(Object o) { 2703  return MapMakerInternalMap.this.remove(o) != null; 2704  } 2705  2706  @Override 2707  public void clear() { 2708  MapMakerInternalMap.this.clear(); 2709  } 2710  } 2711  2712  @WeakOuter 2713  final class Values extends AbstractCollection<V> { 2714  2715  @Override 2716  public Iterator<V> iterator() { 2717  return new ValueIterator(); 2718  } 2719  2720  @Override 2721  public int size() { 2722  return MapMakerInternalMap.this.size(); 2723  } 2724  2725  @Override 2726  public boolean isEmpty() { 2727  return MapMakerInternalMap.this.isEmpty(); 2728  } 2729  2730  @Override 2731  public boolean contains(Object o) { 2732  return MapMakerInternalMap.this.containsValue(o); 2733  } 2734  2735  @Override 2736  public void clear() { 2737  MapMakerInternalMap.this.clear(); 2738  } 2739  2740  // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android. 2741  // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508 2742  2743  @Override 2744  public Object[] toArray() { 2745  return toArrayList(this).toArray(); 2746  } 2747  2748  @Override 2749  public <T> T[] toArray(T[] a) { 2750  return toArrayList(this).toArray(a); 2751  } 2752  } 2753  2754  @WeakOuter 2755  final class EntrySet extends SafeToArraySet<Entry<K, V>> { 2756  2757  @Override 2758  public Iterator<Entry<K, V>> iterator() { 2759  return new EntryIterator(); 2760  } 2761  2762  @Override 2763  public boolean contains(Object o) { 2764  if (!(o instanceof Entry)) { 2765  return false; 2766  } 2767  Entry<?, ?> e = (Entry<?, ?>) o; 2768  Object key = e.getKey(); 2769  if (key == null) { 2770  return false; 2771  } 2772  V v = MapMakerInternalMap.this.get(key); 2773  2774  return v != null && valueEquivalence().equivalent(e.getValue(), v); 2775  } 2776  2777  @Override 2778  public boolean remove(Object o) { 2779  if (!(o instanceof Entry)) { 2780  return false; 2781  } 2782  Entry<?, ?> e = (Entry<?, ?>) o; 2783  Object key = e.getKey(); 2784  return key != null && MapMakerInternalMap.this.remove(key, e.getValue()); 2785  } 2786  2787  @Override 2788  public int size() { 2789  return MapMakerInternalMap.this.size(); 2790  } 2791  2792  @Override 2793  public boolean isEmpty() { 2794  return MapMakerInternalMap.this.isEmpty(); 2795  } 2796  2797  @Override 2798  public void clear() { 2799  MapMakerInternalMap.this.clear(); 2800  } 2801  } 2802  2803  private abstract static class SafeToArraySet<E> extends AbstractSet<E> { 2804  // super.toArray() may misbehave if size() is inaccurate, at least on old versions of Android. 2805  // https://code.google.com/p/android/issues/detail?id=36519 / http://r.android.com/47508 2806  2807  @Override 2808  public Object[] toArray() { 2809  return toArrayList(this).toArray(); 2810  } 2811  2812  @Override 2813  public <T> T[] toArray(T[] a) { 2814  return toArrayList(this).toArray(a); 2815  } 2816  } 2817  2818  private static <E> ArrayList<E> toArrayList(Collection<E> c) { 2819  // Avoid calling ArrayList(Collection), which may call back into toArray. 2820  ArrayList<E> result = new ArrayList<>(c.size()); 2821  Iterators.addAll(result, c.iterator()); 2822  return result; 2823  } 2824  2825  // Serialization Support 2826  2827  private static final long serialVersionUID = 5; 2828  2829  Object writeReplace() { 2830  return new SerializationProxy<>( 2831  entryHelper.keyStrength(), 2832  entryHelper.valueStrength(), 2833  keyEquivalence, 2834  entryHelper.valueStrength().defaultEquivalence(), 2835  concurrencyLevel, 2836  this); 2837  } 2838  2839  /** 2840  * The actual object that gets serialized. Unfortunately, readResolve() doesn't get called when a 2841  * circular dependency is present, so the proxy must be able to behave as the map itself. 2842  */ 2843  abstract static class AbstractSerializationProxy<K, V> extends ForwardingConcurrentMap<K, V> 2844  implements Serializable { 2845  private static final long serialVersionUID = 3; 2846  2847  final Strength keyStrength; 2848  final Strength valueStrength; 2849  final Equivalence<Object> keyEquivalence; 2850  final Equivalence<Object> valueEquivalence; 2851  final int concurrencyLevel; 2852  2853  transient ConcurrentMap<K, V> delegate; 2854  2855  AbstractSerializationProxy( 2856  Strength keyStrength, 2857  Strength valueStrength, 2858  Equivalence<Object> keyEquivalence, 2859  Equivalence<Object> valueEquivalence, 2860  int concurrencyLevel, 2861  ConcurrentMap<K, V> delegate) { 2862  this.keyStrength = keyStrength; 2863  this.valueStrength = valueStrength; 2864  this.keyEquivalence = keyEquivalence; 2865  this.valueEquivalence = valueEquivalence; 2866  this.concurrencyLevel = concurrencyLevel; 2867  this.delegate = delegate; 2868  } 2869  2870  @Override 2871  protected ConcurrentMap<K, V> delegate() { 2872  return delegate; 2873  } 2874  2875  void writeMapTo(ObjectOutputStream out) throws IOException { 2876  out.writeInt(delegate.size()); 2877  for (Entry<K, V> entry : delegate.entrySet()) { 2878  out.writeObject(entry.getKey()); 2879  out.writeObject(entry.getValue()); 2880  } 2881  out.writeObject(null); // terminate entries 2882  } 2883  2884  @SuppressWarnings("deprecation") // serialization of deprecated feature 2885  MapMaker readMapMaker(ObjectInputStream in) throws IOException { 2886  int size = in.readInt(); 2887  return new MapMaker() 2888  .initialCapacity(size) 2889  .setKeyStrength(keyStrength) 2890  .setValueStrength(valueStrength) 2891  .keyEquivalence(keyEquivalence) 2892  .concurrencyLevel(concurrencyLevel); 2893  } 2894  2895  @SuppressWarnings("unchecked") 2896  void readEntries(ObjectInputStream in) throws IOException, ClassNotFoundException { 2897  while (true) { 2898  K key = (K) in.readObject(); 2899  if (key == null) { 2900  break; // terminator 2901  } 2902  V value = (V) in.readObject(); 2903  delegate.put(key, value); 2904  } 2905  } 2906  } 2907  2908  /** 2909  * The actual object that gets serialized. Unfortunately, readResolve() doesn't get called when a 2910  * circular dependency is present, so the proxy must be able to behave as the map itself. 2911  */ 2912  private static final class SerializationProxy<K, V> extends AbstractSerializationProxy<K, V> { 2913  private static final long serialVersionUID = 3; 2914  2915  SerializationProxy( 2916  Strength keyStrength, 2917  Strength valueStrength, 2918  Equivalence<Object> keyEquivalence, 2919  Equivalence<Object> valueEquivalence, 2920  int concurrencyLevel, 2921  ConcurrentMap<K, V> delegate) { 2922  super( 2923  keyStrength, valueStrength, keyEquivalence, valueEquivalence, concurrencyLevel, delegate); 2924  } 2925  2926  private void writeObject(ObjectOutputStream out) throws IOException { 2927  out.defaultWriteObject(); 2928  writeMapTo(out); 2929  } 2930  2931  private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 2932  in.defaultReadObject(); 2933  MapMaker mapMaker = readMapMaker(in); 2934  delegate = mapMaker.makeMap(); 2935  readEntries(in); 2936  } 2937  2938  private Object readResolve() { 2939  return delegate; 2940  } 2941  } 2942 }