Coverage Summary for Class: MapRetrievalCache (com.google.common.graph)

Class Method, % Line, %
MapRetrievalCache 0% (0/6) 0% (0/26)
MapRetrievalCache$CacheEntry 0% (0/1) 0% (0/3)
Total 0% (0/7) 0% (0/29)


1 /* 2  * Copyright (C) 2016 The Guava Authors 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  * http://www.apache.org/licenses/LICENSE-2.0 9  * 10  * Unless required by applicable law or agreed to in writing, software 11  * distributed under the License is distributed on an "AS IS" BASIS, 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13  * See the License for the specific language governing permissions and 14  * limitations under the License. 15  */ 16  17 package com.google.common.graph; 18  19 import static com.google.common.base.Preconditions.checkNotNull; 20  21 import java.util.Map; 22 import javax.annotation.CheckForNull; 23  24 /** 25  * A {@link MapIteratorCache} that adds additional caching. In addition to the caching provided by 26  * {@link MapIteratorCache}, this structure caches values for the two most recently retrieved keys. 27  * 28  * @author James Sexton 29  */ 30 @ElementTypesAreNonnullByDefault 31 final class MapRetrievalCache<K, V> extends MapIteratorCache<K, V> { 32  // See the note about volatile in the superclass. 33  @CheckForNull private transient volatile CacheEntry<K, V> cacheEntry1; 34  @CheckForNull private transient volatile CacheEntry<K, V> cacheEntry2; 35  36  MapRetrievalCache(Map<K, V> backingMap) { 37  super(backingMap); 38  } 39  40  @SuppressWarnings("unchecked") // Safe because we only cast if key is found in map. 41  @Override 42  @CheckForNull 43  V get(Object key) { 44  checkNotNull(key); 45  V value = getIfCached(key); 46  if (value != null) { 47  return value; 48  } 49  50  value = getWithoutCaching(key); 51  if (value != null) { 52  addToCache((K) key, value); 53  } 54  return value; 55  } 56  57  // Internal methods (package-visible, but treat as only subclass-visible) 58  59  @Override 60  @CheckForNull 61  V getIfCached(@CheckForNull Object key) { 62  V value = super.getIfCached(key); 63  if (value != null) { 64  return value; 65  } 66  67  // Store a local reference to the cache entry. If the backing map is immutable, this, 68  // in combination with immutable cache entries, will ensure a thread-safe cache. 69  CacheEntry<K, V> entry; 70  71  // Check cache. We use == on purpose because it's cheaper and a cache miss is ok. 72  entry = cacheEntry1; 73  if (entry != null && entry.key == key) { 74  return entry.value; 75  } 76  entry = cacheEntry2; 77  if (entry != null && entry.key == key) { 78  // Promote second cache entry to first so the access pattern 79  // [K1, K2, K1, K3, K1, K4...] still hits the cache half the time. 80  addToCache(entry); 81  return entry.value; 82  } 83  return null; 84  } 85  86  @Override 87  void clearCache() { 88  super.clearCache(); 89  cacheEntry1 = null; 90  cacheEntry2 = null; 91  } 92  93  private void addToCache(K key, V value) { 94  addToCache(new CacheEntry<K, V>(key, value)); 95  } 96  97  private void addToCache(CacheEntry<K, V> entry) { 98  // Slide new entry into first cache position. Drop previous entry in second cache position. 99  cacheEntry2 = cacheEntry1; 100  cacheEntry1 = entry; 101  } 102  103  private static final class CacheEntry<K, V> { 104  final K key; 105  final V value; 106  107  CacheEntry(K key, V value) { 108  this.key = key; 109  this.value = value; 110  } 111  } 112 }