16859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert/* 26859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Copyright (C) 2010 The Android Open Source Project 36859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * 46859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); 56859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * you may not use this file except in compliance with the License. 66859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * You may obtain a copy of the License at 76859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * 86859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0 96859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * 106859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Unless required by applicable law or agreed to in writing, software 116859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS, 126859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * See the License for the specific language governing permissions and 146859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * limitations under the License. 156859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert */ 166859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 176859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringertpackage com.android.quicksearchbox.util; 186859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 196859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringertimport android.util.Log; 206859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 216859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringertimport java.util.ArrayList; 226859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringertimport java.util.List; 236859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 246859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert/** 256859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Abstract base class for a one-place cache that holds a value that is produced 266859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * asynchronously. 276859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * 286859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * @param <A> The type of the data held in the cache. 296859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert */ 30e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwoodpublic abstract class CachedLater<A> implements NowOrLater<A> { 316859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 326859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert private static final String TAG = "QSB.AsyncCache"; 3313b4f2dc4b339790c2b9b0220be47c8e77fd61eaMathew Inwood private static final boolean DBG = false; 346859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 356859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert private final Object mLock = new Object(); 366859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 376859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert private A mValue; 386859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 39e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood private boolean mCreating; 406859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert private boolean mValid; 416859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 42e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood private List<Consumer<? super A>> mWaitingConsumers; 436859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 446859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert /** 456859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Creates the object to store in the cache. This method must call 466859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * {@link #store} when it's done. 476859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * This method must not block. 486859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert */ 496859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert protected abstract void create(); 506859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 516859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert /** 526859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Saves a new value to the cache. 536859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert */ 546859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert protected void store(A value) { 557f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "store()"); 56e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood List<Consumer<? super A>> waitingConsumers; 576859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert synchronized (mLock) { 586859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert mValue = value; 596859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert mValid = true; 607f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert mCreating = false; 616859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert waitingConsumers = mWaitingConsumers; 626859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert mWaitingConsumers = null; 636859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 646859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert if (waitingConsumers != null) { 65e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood for (Consumer<? super A> consumer : waitingConsumers) { 666859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert if (DBG) Log.d(TAG, "Calling consumer: " + consumer); 676859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert consumer.consume(value); 686859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 696859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 706859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 716859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 726859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert /** 736859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Gets the value. 746859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * 756859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * @param consumer A consumer that will be given the cached value. 766859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * The consumer may be called synchronously, or asynchronously on 776859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * an unspecified thread. 786859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert */ 79e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood public void getLater(Consumer<? super A> consumer) { 807f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "getLater()"); 816859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert boolean valid; 826859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert A value; 836859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert synchronized (mLock) { 846859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert valid = mValid; 856859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert value = mValue; 866859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert if (!valid) { 87e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood if (mWaitingConsumers == null) { 88e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood mWaitingConsumers = new ArrayList<Consumer<? super A>>(); 89e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 906859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert mWaitingConsumers.add(consumer); 916859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 926859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 936859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert if (valid) { 947f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "valid, calling consumer synchronously"); 956859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert consumer.consume(value); 966859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } else { 97e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood boolean create = false; 98e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood synchronized (mLock) { 99e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood if (!mCreating) { 100e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood mCreating = true; 101e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood create = true; 102e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 103e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 1047f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (create) { 1057f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "not valid, calling create()"); 1067f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert create(); 1077f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert } else { 1087f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "not valid, already creating"); 1097f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert } 1106859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 1116859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 1126859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 1136859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert /** 1146859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert * Clears the cache. 1156859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert */ 1166859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert public void clear() { 1177f5ff91319a8433abd92f3e3179158e38391e159Bjorn Bringert if (DBG) Log.d(TAG, "clear()"); 1186859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert synchronized (mLock) { 1196859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert mValue = null; 1206859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert mValid = false; 1216859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 1226859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert } 1236859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert 124e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood public boolean haveNow() { 125e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood synchronized (mLock) { 126e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood return mValid; 127e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 128e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 129e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood 130e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood public synchronized A getNow() { 131e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood synchronized (mLock) { 132e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood if (!haveNow()) { 133e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood throw new IllegalStateException("getNow() called when haveNow() is false"); 134e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 135e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood return mValue; 136e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 137e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood } 138e29d52aa72c96c3147fa91d83aeb8dafc6d1f578Mathew Inwood 1396859aead3af0680b2c9dc326244aa89835c2c852Bjorn Bringert} 140