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 }