193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/*
293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Copyright (C) 2013 The Android Open Source Project
393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein *
493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Licensed under the Apache License, Version 2.0 (the "License");
593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * you may not use this file except in compliance with the License.
693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * You may obtain a copy of the License at
793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein *
893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein *      http://www.apache.org/licenses/LICENSE-2.0
993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein *
1093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Unless required by applicable law or agreed to in writing, software
1193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * distributed under the License is distributed on an "AS IS" BASIS,
1293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * See the License for the specific language governing permissions and
1493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * limitations under the License.
1593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */
1693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
1793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpackage com.android.bitmap;
1893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
1993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.util.Log;
2093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport android.util.LruCache;
21a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kung
22a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kungimport com.android.bitmap.util.Trace;
23a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kung
2493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.LinkedHashMap;
2593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.Map;
2693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinimport java.util.concurrent.LinkedBlockingQueue;
2793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
2893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein/**
2993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * An alternative implementation of a pool+cache. This implementation only counts
3093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * unreferenced objects in its size calculation. Internally, it never evicts from
3193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * its cache, and instead {@link #poll()} is allowed to return unreferenced cache
3293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * entries.
3393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <p>
3493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * You would only use this kind of cache if your objects are interchangeable and
3593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * have significant allocation cost, and if your memory footprint is somewhat
3693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * flexible.
3793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <p>
3893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * Because this class only counts unreferenced objects toward targetSize,
3993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * it will have a total memory footprint of:
4093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * <code>(targetSize) + (# of threads concurrently writing to cache) +
4193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein * (total size of still-referenced entries)</code>
4293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein *
4393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein */
4493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzsteinpublic class UnrefedPooledCache<K, V extends Poolable> implements PooledCache<K, V> {
4593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
4693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    private final LinkedHashMap<K, V> mCache;
4793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    private final LinkedBlockingQueue<V> mPool;
4893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    private final int mTargetSize;
4993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    private final LruCache<K, V> mNonPooledCache;
5093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
51cea0c012d538f11b3ee97d4b7e78f4c1ea73d5beMark Wei    private static final boolean DEBUG = DecodeTask.DEBUG;
5293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    private static final String TAG = UnrefedPooledCache.class.getSimpleName();
5393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
5493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    /**
5593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param targetSize not exactly a max size in practice
5693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * @param nonPooledFraction the fractional portion in the range [0.0,1.0] of targetSize to
5793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     * dedicate to non-poolable entries
5893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein     */
5993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public UnrefedPooledCache(int targetSize, float nonPooledFraction) {
6093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        mCache = new LinkedHashMap<K, V>(0, 0.75f, true);
6193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        mPool = new LinkedBlockingQueue<V>();
6293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final int nonPooledSize = Math.round(targetSize * nonPooledFraction);
6393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (nonPooledSize > 0) {
6493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            mNonPooledCache = new NonPooledCache(nonPooledSize);
6593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        } else {
6693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            mNonPooledCache = null;
6793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
6893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        mTargetSize = targetSize - nonPooledSize;
6993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
7093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
7193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    @Override
7293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public V get(K key, boolean incrementRefCount) {
7393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        Trace.beginSection("cache get");
7493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        synchronized (mCache) {
7593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            V result = mCache.get(key);
7693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            if (result == null && mNonPooledCache != null) {
7793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                result = mNonPooledCache.get(key);
7893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            }
7993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            if (incrementRefCount && result != null) {
8093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                result.acquireReference();
8193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            }
8293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            Trace.endSection();
8393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            return result;
8493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
8593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
8693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
8793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    @Override
8893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public V put(K key, V value) {
8993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        Trace.beginSection("cache put");
90a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kung        // Null values not supported.
91a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kung        if (value == null) {
929f42e5cd4e26c6d3d175491c524763d1aefe8643Mark Wei            Trace.endSection();
93a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kung            return null;
94a07e0af0f1997ce3d40df6a8a9f44cb0b2e4c07fJames Kung        }
9593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        synchronized (mCache) {
9693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            final V prev;
9793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            if (value.isEligibleForPooling()) {
9893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                prev = mCache.put(key, value);
9993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            } else if (mNonPooledCache != null) {
10093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                prev = mNonPooledCache.put(key, value);
10193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            } else {
10293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                prev = null;
10393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            }
10493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            Trace.endSection();
10593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            return prev;
10693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
10793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
10893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
10993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    @Override
11093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public void offer(V value) {
11193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        Trace.beginSection("pool offer");
11293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (value.getRefCount() != 0 || !value.isEligibleForPooling()) {
1132d10993c4276db5b28ef7cb909362fbbc26c460cRuben            Trace.endSection();
11493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            throw new IllegalArgumentException("unexpected offer of an invalid object: " + value);
11593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
11693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        mPool.offer(value);
11793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        Trace.endSection();
11893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
11993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
12093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    @Override
12193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public V poll() {
12293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        Trace.beginSection("pool poll");
12393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        final V pooled = mPool.poll();
12493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (pooled != null) {
12593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            Trace.endSection();
12693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            return pooled;
12793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
12893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
12993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        synchronized (mCache) {
13093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            int unrefSize = 0;
13193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            Map.Entry<K, V> eldestUnref = null;
13293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            for (Map.Entry<K, V> entry : mCache.entrySet()) {
13393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                final V value = entry.getValue();
13493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (value.getRefCount() > 0 || !value.isEligibleForPooling()) {
13593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    continue;
13693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
13793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (eldestUnref == null) {
13893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    eldestUnref = entry;
13993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
14093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                unrefSize += sizeOf(value);
14193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (unrefSize > mTargetSize) {
14293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    break;
14393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
14493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            }
14593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            // only return a scavenged cache entry if the cache has enough
14693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            // eligible (unreferenced) items
14793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            if (unrefSize <= mTargetSize) {
14893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (DEBUG) {
14993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    Log.e(TAG, "POOL SCAVENGE FAILED, cache not fully warm yet. szDelta="
15093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                            + (mTargetSize-unrefSize));
15193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
15293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                Trace.endSection();
15393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                return null;
15493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            } else {
15593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                mCache.remove(eldestUnref.getKey());
15693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (DEBUG) {
15793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    Log.e(TAG, "POOL SCAVENGE SUCCESS, oldKey=" + eldestUnref.getKey());
15893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
15993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                Trace.endSection();
16093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                return eldestUnref.getValue();
16193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            }
16293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
16393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
16493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
16593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    protected int sizeOf(V value) {
16693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        return 1;
16793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
16893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
16993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    @Override
17093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public String toDebugString() {
17193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        if (DEBUG) {
17293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            final StringBuilder sb = new StringBuilder("[");
17393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            sb.append(super.toString());
17493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            int size = 0;
17593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            synchronized (mCache) {
17693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append(" poolCount=");
17793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append(mPool.size());
17893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append(" cacheSize=");
17993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append(mCache.size());
18093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (mNonPooledCache != null) {
18193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append(" nonPooledCacheSize=");
18293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append(mNonPooledCache.size());
18393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
18493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append("\n---------------------");
18593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                for (V val : mPool) {
18693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    size += sizeOf(val);
18793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append("\n\tpool item: ");
18893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append(val);
18993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
19093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append("\n---------------------");
19193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                for (Map.Entry<K, V> item : mCache.entrySet()) {
19293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    final V val = item.getValue();
19393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append("\n\tcache key=");
19493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append(item.getKey());
19593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append(" val=");
19693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append(val);
19793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    size += sizeOf(val);
19893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
19993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append("\n---------------------");
20093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                if (mNonPooledCache != null) {
20193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    for (Map.Entry<K, V> item : mNonPooledCache.snapshot().entrySet()) {
20293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                        final V val = item.getValue();
20393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                        sb.append("\n\tnon-pooled cache key=");
20493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                        sb.append(item.getKey());
20593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                        sb.append(" val=");
20693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                        sb.append(val);
20793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                        size += sizeOf(val);
20893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    }
20993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                    sb.append("\n---------------------");
21093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                }
21193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein                sb.append("\nTOTAL SIZE=" + size);
21293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            }
21393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            sb.append("]");
21493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            return sb.toString();
21593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        } else {
21693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            return null;
21793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
21893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
21993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
22093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    private class NonPooledCache extends LruCache<K, V> {
22193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
22293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        public NonPooledCache(int maxSize) {
22393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            super(maxSize);
22493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
22593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
22693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        @Override
22793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        protected int sizeOf(K key, V value) {
22893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein            return UnrefedPooledCache.this.sizeOf(value);
22993a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        }
23093a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
23193a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
23293a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein
23393a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    @Override
23493a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    public void clear() {
23593a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        mCache.clear();
23693a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein        mPool.clear();
23793a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein    }
23893a35b93dc582e38ff8ee5979754a16b4bf4da0cSam Blitzstein}
239