Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright (C) 2009 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.gallery3d.common;
     18 
     19 import java.lang.ref.ReferenceQueue;
     20 import java.lang.ref.WeakReference;
     21 import java.util.HashMap;
     22 import java.util.LinkedHashMap;
     23 import java.util.Map;
     24 
     25 /**
     26  * An LRU cache which stores recently inserted entries and all entries ever
     27  * inserted which still has a strong reference elsewhere.
     28  */
     29 public class LruCache<K, V> {
     30 
     31     private final HashMap<K, V> mLruMap;
     32     private final HashMap<K, Entry<K, V>> mWeakMap =
     33             new HashMap<K, Entry<K, V>>();
     34     private ReferenceQueue<V> mQueue = new ReferenceQueue<V>();
     35 
     36     @SuppressWarnings("serial")
     37     public LruCache(final int capacity) {
     38         mLruMap = new LinkedHashMap<K, V>(16, 0.75f, true) {
     39             @Override
     40             protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
     41                 return size() > capacity;
     42             }
     43         };
     44     }
     45 
     46     private static class Entry<K, V> extends WeakReference<V> {
     47         K mKey;
     48 
     49         public Entry(K key, V value, ReferenceQueue<V> queue) {
     50             super(value, queue);
     51             mKey = key;
     52         }
     53     }
     54 
     55     @SuppressWarnings("unchecked")
     56     private void cleanUpWeakMap() {
     57         Entry<K, V> entry = (Entry<K, V>) mQueue.poll();
     58         while (entry != null) {
     59             mWeakMap.remove(entry.mKey);
     60             entry = (Entry<K, V>) mQueue.poll();
     61         }
     62     }
     63 
     64     public synchronized boolean containsKey(K key) {
     65         cleanUpWeakMap();
     66         return mWeakMap.containsKey(key);
     67     }
     68 
     69     public synchronized V put(K key, V value) {
     70         cleanUpWeakMap();
     71         mLruMap.put(key, value);
     72         Entry<K, V> entry = mWeakMap.put(
     73                 key, new Entry<K, V>(key, value, mQueue));
     74         return entry == null ? null : entry.get();
     75     }
     76 
     77     public synchronized V get(K key) {
     78         cleanUpWeakMap();
     79         V value = mLruMap.get(key);
     80         if (value != null) return value;
     81         Entry<K, V> entry = mWeakMap.get(key);
     82         return entry == null ? null : entry.get();
     83     }
     84 
     85     public synchronized void clear() {
     86         mLruMap.clear();
     87         mWeakMap.clear();
     88         mQueue = new ReferenceQueue<V>();
     89     }
     90 }
     91