1f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/* 2f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Copyright (C) 2009 The Android Open Source Project 3f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 4f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Licensed under the Apache License, Version 2.0 (the "License"); 5f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * you may not use this file except in compliance with the License. 6f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * You may obtain a copy of the License at 7f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 8f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * http://www.apache.org/licenses/LICENSE-2.0 9f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * 10f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * Unless required by applicable law or agreed to in writing, software 11f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * distributed under the License is distributed on an "AS IS" BASIS, 12f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * See the License for the specific language governing permissions and 14f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * limitations under the License. 15f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 16f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 17f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpackage com.android.gallery3d.common; 18f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 19f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.lang.ref.ReferenceQueue; 20f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.lang.ref.WeakReference; 21f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.HashMap; 22f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.LinkedHashMap; 23f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linimport java.util.Map; 24f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 25f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin/** 26f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * An LRU cache which stores recently inserted entries and all entries ever 27f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin * inserted which still has a strong reference elsewhere. 28f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin */ 29f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Linpublic class LruCache<K, V> { 30f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 31f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final HashMap<K, V> mLruMap; 32f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private final HashMap<K, Entry<K, V>> mWeakMap = 33f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin new HashMap<K, Entry<K, V>>(); 34f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private ReferenceQueue<V> mQueue = new ReferenceQueue<V>(); 35f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 36f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("serial") 37f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public LruCache(final int capacity) { 38f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mLruMap = new LinkedHashMap<K, V>(16, 0.75f, true) { 39f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @Override 40f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { 41f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return size() > capacity; 42f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 43f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin }; 44f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 45f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 46f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private static class Entry<K, V> extends WeakReference<V> { 47f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin K mKey; 48f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 49f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public Entry(K key, V value, ReferenceQueue<V> queue) { 50f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin super(value, queue); 51f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mKey = key; 52f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 53f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 54f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 55f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin @SuppressWarnings("unchecked") 56f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin private void cleanUpWeakMap() { 57f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Entry<K, V> entry = (Entry<K, V>) mQueue.poll(); 58f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin while (entry != null) { 59f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mWeakMap.remove(entry.mKey); 60f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin entry = (Entry<K, V>) mQueue.poll(); 61f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 62f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 63f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 64f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized boolean containsKey(K key) { 65f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cleanUpWeakMap(); 66f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return mWeakMap.containsKey(key); 67f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 68f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 69f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized V put(K key, V value) { 70f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cleanUpWeakMap(); 71f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mLruMap.put(key, value); 72f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Entry<K, V> entry = mWeakMap.put( 73f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin key, new Entry<K, V>(key, value, mQueue)); 74f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return entry == null ? null : entry.get(); 75f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 76f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 77f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized V get(K key) { 78f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin cleanUpWeakMap(); 79f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin V value = mLruMap.get(key); 80f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin if (value != null) return value; 81f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin Entry<K, V> entry = mWeakMap.get(key); 82f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin return entry == null ? null : entry.get(); 83f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 84f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin 85f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin public synchronized void clear() { 86f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mLruMap.clear(); 87f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mWeakMap.clear(); 88f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin mQueue = new ReferenceQueue<V>(); 89f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin } 90f9a0a4306d589b4a4e20554fed512a603426bfa1Owen Lin} 91