194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng/*
294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Copyright (C) 2011 The Android Open Source Project
394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *
494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Licensed under the Apache License, Version 2.0 (the "License");
594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * you may not use this file except in compliance with the License.
694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * You may obtain a copy of the License at
794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *
894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *      http://www.apache.org/licenses/LICENSE-2.0
994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *
1094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Unless required by applicable law or agreed to in writing, software
1194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * distributed under the License is distributed on an "AS IS" BASIS,
1294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * See the License for the specific language governing permissions and
1494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * limitations under the License.
1594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */
1694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
1794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengpackage com.android.dialer.util;
1894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
1994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport android.util.LruCache;
2094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
21e38e9ab6195950d2083efde283788b91d03354c4Yorke Leeimport com.android.contacts.common.testing.NeededForTesting;
2294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
2394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport java.util.concurrent.atomic.AtomicInteger;
2494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
2594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport javax.annotation.concurrent.Immutable;
2694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengimport javax.annotation.concurrent.ThreadSafe;
2794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
2894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng/**
2994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * An LRU cache in which all items can be marked as expired at a given time and it is possible to
3094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * query whether a particular cached value is expired or not.
3194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
3294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * A typical use case for this is caching of values which are expensive to compute but which are
3394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * still useful when out of date.
3494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
3594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Consider a cache for contact information:
3694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <pre>{@code
3794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     private ExpirableCache<String, Contact> mContactCache;}</pre>
3894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * which stores the contact information for a given phone number.
3994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
4094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * When we need to store contact information for a given phone number, we can look up the info in
4194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * the cache:
4294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <pre>{@code
4394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     CachedValue<Contact> cachedContact = mContactCache.getCachedValue(phoneNumber);
4494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * }</pre>
4594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * We might also want to fetch the contact information again if the item is expired.
4694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <pre>
4794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     if (cachedContact.isExpired()) {
4894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *         fetchContactForNumber(phoneNumber,
4994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *                 new FetchListener() {
5094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *                     &#64;Override
5194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *                     public void onFetched(Contact contact) {
5294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *                         mContactCache.put(phoneNumber, contact);
5394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *                     }
5494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *                 });
5594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     }</pre>
5694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * and insert it back into the cache when the fetch completes.
5794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
5894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * At a certain point we want to expire the content of the cache because we know the content may
5994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * no longer be up-to-date, for instance, when resuming the activity this is shown into:
6094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <pre>
6194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     &#64;Override
6294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     protected onResume() {
6394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *         // We were paused for some time, the cached value might no longer be up to date.
6494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *         mContactCache.expireAll();
6594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *         super.onResume();
6694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *     }
6794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * </pre>
6894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * The values will be still available from the cache, but they will be expired.
6994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
7094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * If interested only in the value itself, not whether it is expired or not, one should use the
7194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * {@link #getPossiblyExpired(Object)} method. If interested only in non-expired values, one should
7294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * use the {@link #get(Object)} method instead.
7394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
7494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * This class wraps around an {@link LruCache} instance: it follows the {@link LruCache} behavior
7594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * for evicting items when the cache is full. It is possible to supply your own subclass of LruCache
7694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * by using the {@link #create(LruCache)} method, which can define a custom expiration policy.
7794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * Since the underlying cache maps keys to cached values it can determine which items are expired
7894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * and which are not, allowing for an implementation that evicts expired items before non expired
7994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * ones.
8094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * <p>
8194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * This class is thread-safe.
8294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng *
8394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * @param <K> the type of the keys
8494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng * @param <V> the type of the values
8594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng */
8694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng@ThreadSafe
8794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Chengpublic class ExpirableCache<K, V> {
8894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
8994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * A cached value stored inside the cache.
9094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
9194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * It provides access to the value stored in the cache but also allows to check whether the
9294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * value is expired.
9394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
9494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param <V> the type of value stored in the cache
9594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
9694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public interface CachedValue<V> {
9794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        /** Returns the value stored in the cache for a given key. */
9894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public V getValue();
9994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
10094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        /**
10194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         * Checks whether the value, while still being present in the cache, is expired.
10294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         *
10394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         * @return true if the value is expired
10494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         */
10594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public boolean isExpired();
10694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
10794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
10894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
10994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Cached values storing the generation at which they were added.
11094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
11194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @Immutable
11294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private static class GenerationalCachedValue<V> implements ExpirableCache.CachedValue<V> {
11394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        /** The value stored in the cache. */
11494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public final V mValue;
11594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        /** The generation at which the value was added to the cache. */
11694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        private final int mGeneration;
11794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        /** The atomic integer storing the current generation of the cache it belongs to. */
11894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        private final AtomicInteger mCacheGeneration;
11994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
12094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        /**
12194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         * @param cacheGeneration the atomic integer storing the generation of the cache in which
12294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         *        this value will be stored
12394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng         */
12494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public GenerationalCachedValue(V value, AtomicInteger cacheGeneration) {
12594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            mValue = value;
12694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            mCacheGeneration = cacheGeneration;
12794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            // Snapshot the current generation.
12894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            mGeneration = mCacheGeneration.get();
12994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
13094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
13194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        @Override
13294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public V getValue() {
13394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            return mValue;
13494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
13594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
13694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        @Override
13794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        public boolean isExpired() {
13894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng            return mGeneration != mCacheGeneration.get();
13994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        }
14094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
14194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
14294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /** The underlying cache used to stored the cached values. */
14394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private LruCache<K, CachedValue<V>> mCache;
14494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
14594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
14694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * The current generation of items added to the cache.
14794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
14894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Items in the cache can belong to a previous generation, but in that case they would be
14994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * expired.
15094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
15194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @see ExpirableCache.CachedValue#isExpired()
15294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
15394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private final AtomicInteger mGeneration;
15494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
15594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    private ExpirableCache(LruCache<K, CachedValue<V>> cache) {
15694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCache = cache;
15794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mGeneration = new AtomicInteger(0);
15894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
15994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
16094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
16194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Returns the cached value for the given key, or null if no value exists.
16294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
16394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * The cached value gives access both to the value associated with the key and whether it is
16494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * expired or not.
16594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
16694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * If not interested in whether the value is expired, use {@link #getPossiblyExpired(Object)}
16794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * instead.
16894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
16994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * If only wants values that are not expired, use {@link #get(Object)} instead.
17094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
17194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param key the key to look up
17294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
17394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public CachedValue<V> getCachedValue(K key) {
17494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return mCache.get(key);
17594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
17694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
17794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
17894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Returns the value for the given key, or null if no value exists.
17994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
18094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * When using this method, it is not possible to determine whether the value is expired or not.
18194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Use {@link #getCachedValue(Object)} to achieve that instead. However, if using
18294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * {@link #getCachedValue(Object)} to determine if an item is expired, one should use the item
18394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * within the {@link CachedValue} and not call {@link #getPossiblyExpired(Object)} to get the
18494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * value afterwards, since that is not guaranteed to return the same value or that the newly
18594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * returned value is in the same state.
18694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
18794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param key the key to look up
18894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
18994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public V getPossiblyExpired(K key) {
19094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        CachedValue<V> cachedValue = getCachedValue(key);
19194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return cachedValue == null ? null : cachedValue.getValue();
19294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
19394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
19494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
19594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Returns the value for the given key only if it is not expired, or null if no value exists or
19694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * is expired.
19794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
19894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * This method will return null if either there is no value associated with this key or if the
19994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * associated value is expired.
20094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
20194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param key the key to look up
20294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
20394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    @NeededForTesting
20494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public V get(K key) {
20594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        CachedValue<V> cachedValue = getCachedValue(key);
20694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return cachedValue == null || cachedValue.isExpired() ? null : cachedValue.getValue();
20794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
20894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
20994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
21094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Puts an item in the cache.
21194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
21294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Newly added item will not be expired until {@link #expireAll()} is next called.
21394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
21494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param key the key to look up
21594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param value the value to associate with the key
21694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
21794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public void put(K key, V value) {
21894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mCache.put(key, newCachedValue(value));
21994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
22094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
22194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
22294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Mark all items currently in the cache as expired.
22394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
22494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Newly added items after this call will be marked as not expired.
22594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
22694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Expiring the items in the cache does not imply they will be evicted.
22794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
22894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public void expireAll() {
22994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        mGeneration.incrementAndGet();
23094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
23194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
23294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
23394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Creates a new {@link CachedValue} instance to be stored in this cache.
23494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
23594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Implementation of {@link LruCache#create(K)} can use this method to create a new entry.
23694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
23794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public CachedValue<V> newCachedValue(V value) {
23894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return new GenerationalCachedValue<V>(value, mGeneration);
23994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
24094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
24194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
24294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Creates a new {@link ExpirableCache} that wraps the given {@link LruCache}.
24394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * <p>
24494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * The created cache takes ownership of the cache passed in as an argument.
24594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
24694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param <K> the type of the keys
24794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param <V> the type of the values
24894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param cache the cache to store the value in
24994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @return the newly created expirable cache
25094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @throws IllegalArgumentException if the cache is not empty
25194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
25294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public static <K, V> ExpirableCache<K, V> create(LruCache<K, CachedValue<V>> cache) {
25394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return new ExpirableCache<K, V>(cache);
25494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
25594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng
25694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    /**
25794b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * Creates a new {@link ExpirableCache} with the given maximum size.
25894b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     *
25994b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param <K> the type of the keys
26094b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @param <V> the type of the values
26194b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     * @return the newly created expirable cache
26294b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng     */
26394b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    public static <K, V> ExpirableCache<K, V> create(int maxSize) {
26494b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng        return create(new LruCache<K, CachedValue<V>>(maxSize));
26594b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng    }
26694b10b530c0fc297e2974e57e094c500d3ee6003Chiao Cheng}
267