1721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor/* 2721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * Copyright (C) 2012 The Android Open Source Project 3721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 4721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * Licensed under the Apache License, Version 2.0 (the "License"); 5721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * you may not use this file except in compliance with the License. 6721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * You may obtain a copy of the License at 7721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 8721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * http://www.apache.org/licenses/LICENSE-2.0 9721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * 10721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * Unless required by applicable law or agreed to in writing, software 11721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * distributed under the License is distributed on an "AS IS" BASIS, 12721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * See the License for the specific language governing permissions and 14721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * limitations under the License. 15721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor */ 1651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 1751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylorpackage com.android.mms.util; 1851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 1951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylorimport java.lang.ref.SoftReference; 2051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylorimport java.util.LinkedHashMap; 2151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylorimport java.util.Map; 2251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 2351e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor/** 24721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * A simple cache with the option of using {@link SoftReference SoftReferences} to play well with 2551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * the garbage collector and an LRU cache eviction algorithm to limit the number 2651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * of {@link SoftReference SoftReferences}. 2751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * <p> 2851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * The interface of this class is a subset of {@link Map}. 2951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * 3051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * from Peter Balwin and books app. 3151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor */ 3251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylorpublic class SimpleCache<K, V> { 3351e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 3451e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor /** 3551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * A simple LRU cache to prevent the number of {@link Map.Entry} instances 3651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * from growing infinitely. 3751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor */ 3851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor @SuppressWarnings("serial") 3951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor private class SoftReferenceMap extends LinkedHashMap<K, SoftReference<V>> { 4051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 4151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor private final int mMaxCapacity; 4251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 4351e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor public SoftReferenceMap(int initialCapacity, int maxCapacity, float loadFactor) { 4451e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor super(initialCapacity, loadFactor, true); 4551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor mMaxCapacity = maxCapacity; 4651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 4751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 4851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor @Override 4951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor protected boolean removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest) { 5051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor return size() > mMaxCapacity; 5151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 5251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 5351e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 54721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor @SuppressWarnings("serial") 55721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private class HardReferenceMap extends LinkedHashMap<K, V> { 56721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 57721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private final int mMaxCapacity; 58721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 59721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public HardReferenceMap(int initialCapacity, int maxCapacity, float loadFactor) { 60721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor super(initialCapacity, loadFactor, true); 61721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mMaxCapacity = maxCapacity; 62721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 63721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 64721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor @Override 65721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { 66721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return size() > mMaxCapacity; 67721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 68721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 69721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor 7051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor private static <V> V unwrap(SoftReference<V> ref) { 7151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor return ref != null ? ref.get() : null; 7251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 7351e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 74721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private final SoftReferenceMap mSoftReferences; 75721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor private final HardReferenceMap mHardReferences; 7651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 7751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor /** 7851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * Constructor. 7951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * 80721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * @param initialCapacity the initial capacity for the cache. 81721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * @param maxCapacity the maximum capacity for the 82721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * cache (this value may be large if soft references are used because 83721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor * {@link SoftReference SoftReferences} don't consume much memory compared to the 8451e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * larger data they typically contain). 8551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * @param loadFactor the initial load balancing factor for the internal 8651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * {@link LinkedHashMap} 8751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor */ 88721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor public SimpleCache(int initialCapacity, int maxCapacity, float loadFactor, 89721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor boolean useHardReferences) { 90721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (useHardReferences) { 91721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mSoftReferences = null; 92721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mHardReferences = new HardReferenceMap(initialCapacity, maxCapacity, loadFactor); 93721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } else { 94721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mSoftReferences = new SoftReferenceMap(initialCapacity, maxCapacity, loadFactor); 95721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mHardReferences = null; 96721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 9751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 9851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 9951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor /** 10051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * See {@link Map#get(Object)}. 10151e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor */ 10251e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor public V get(Object key) { 103721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return mSoftReferences != null ? unwrap(mSoftReferences.get(key)) 104721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor : mHardReferences.get(key); 10551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 10651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 10751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor /** 10851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * See {@link Map#put(Object, Object)}. 10951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor */ 11051e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor public V put(K key, V value) { 111721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor return mSoftReferences != null ? 112721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor unwrap(mSoftReferences.put(key, new SoftReference<V>(value))) 113721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor : mHardReferences.put(key, value); 11451e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 11551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor 11651e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor /** 11751e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor * See {@link Map#clear()}. 11851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor */ 11951e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor public void clear() { 120721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor if (mSoftReferences != null) { 121721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mSoftReferences.clear(); 122721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } else { 123721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor mHardReferences.clear(); 124721ad07121cb9b0cd76bdbbc88494aa8f4d45a6dTom Taylor } 12551e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor } 126b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor 127b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor /** 128b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor * See {@link Map#remove(Object)}. 129b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor */ 130b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor public V remove(K key) { 131b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor if (mSoftReferences != null) { 132b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor return unwrap(mSoftReferences.remove(key)); 133b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor } else { 134b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor return mHardReferences.remove(key); 135b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor } 136b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor } 137b8eae066a7ba60722de07300bf990d519f5c81d8Tom Taylor 13851e4621fa12400b1e79cc18b7bb0f9a83af6b622Tom Taylor} 139