• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
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.android.mms.util;
18 
19 import java.lang.ref.SoftReference;
20 import java.util.LinkedHashMap;
21 import java.util.Map;
22 
23 /**
24  * A simple cache with the option of using {@link SoftReference SoftReferences} to play well with
25  * the garbage collector and an LRU cache eviction algorithm to limit the number
26  * of {@link SoftReference SoftReferences}.
27  * <p>
28  * The interface of this class is a subset of {@link Map}.
29  *
30  * from Peter Balwin and books app.
31  */
32 public class SimpleCache<K, V> {
33 
34     /**
35      * A simple LRU cache to prevent the number of {@link Map.Entry} instances
36      * from growing infinitely.
37      */
38     @SuppressWarnings("serial")
39     private class SoftReferenceMap extends LinkedHashMap<K, SoftReference<V>> {
40 
41         private final int mMaxCapacity;
42 
SoftReferenceMap(int initialCapacity, int maxCapacity, float loadFactor)43         public SoftReferenceMap(int initialCapacity, int maxCapacity, float loadFactor) {
44             super(initialCapacity, loadFactor, true);
45             mMaxCapacity = maxCapacity;
46         }
47 
48         @Override
removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest)49         protected boolean removeEldestEntry(Map.Entry<K, SoftReference<V>> eldest) {
50             return size() > mMaxCapacity;
51         }
52     }
53 
54     @SuppressWarnings("serial")
55     private class HardReferenceMap extends LinkedHashMap<K, V> {
56 
57         private final int mMaxCapacity;
58 
HardReferenceMap(int initialCapacity, int maxCapacity, float loadFactor)59         public HardReferenceMap(int initialCapacity, int maxCapacity, float loadFactor) {
60             super(initialCapacity, loadFactor, true);
61             mMaxCapacity = maxCapacity;
62         }
63 
64         @Override
removeEldestEntry(Map.Entry<K, V> eldest)65         protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
66             return size() > mMaxCapacity;
67         }
68     }
69 
unwrap(SoftReference<V> ref)70     private static <V> V unwrap(SoftReference<V> ref) {
71         return ref != null ? ref.get() : null;
72     }
73 
74     private final SoftReferenceMap mSoftReferences;
75     private final HardReferenceMap mHardReferences;
76 
77     /**
78      * Constructor.
79      *
80      * @param initialCapacity the initial capacity for the cache.
81      * @param maxCapacity the maximum capacity for the
82      *            cache (this value may be large if soft references are used because
83      *            {@link SoftReference SoftReferences} don't consume much memory compared to the
84      *            larger data they typically contain).
85      * @param loadFactor the initial load balancing factor for the internal
86      *            {@link LinkedHashMap}
87      */
SimpleCache(int initialCapacity, int maxCapacity, float loadFactor, boolean useHardReferences)88     public SimpleCache(int initialCapacity, int maxCapacity, float loadFactor,
89             boolean useHardReferences) {
90         if (useHardReferences) {
91             mSoftReferences = null;
92             mHardReferences = new HardReferenceMap(initialCapacity, maxCapacity, loadFactor);
93         } else {
94             mSoftReferences = new SoftReferenceMap(initialCapacity, maxCapacity, loadFactor);
95             mHardReferences = null;
96         }
97     }
98 
99     /**
100      * See {@link Map#get(Object)}.
101      */
get(Object key)102     public V get(Object key) {
103         return mSoftReferences != null ? unwrap(mSoftReferences.get(key))
104                 : mHardReferences.get(key);
105     }
106 
107     /**
108      * See {@link Map#put(Object, Object)}.
109      */
put(K key, V value)110     public V put(K key, V value) {
111         return mSoftReferences != null ?
112                 unwrap(mSoftReferences.put(key, new SoftReference<V>(value)))
113                 : mHardReferences.put(key, value);
114     }
115 
116     /**
117      * See {@link Map#clear()}.
118      */
clear()119     public void clear() {
120         if (mSoftReferences != null) {
121             mSoftReferences.clear();
122         } else {
123             mHardReferences.clear();
124         }
125     }
126 
127     /**
128      * See {@link Map#remove(Object)}.
129      */
remove(K key)130     public V remove(K key) {
131         if (mSoftReferences != null) {
132             return unwrap(mSoftReferences.remove(key));
133         } else {
134             return mHardReferences.remove(key);
135         }
136     }
137 
138 }
139