diff --git a/android/guava-tests/test/com/google/common/base/SuppliersTest.java b/android/guava-tests/test/com/google/common/base/SuppliersTest.java index 10cd0b040e2a..4101f4a6b9c1 100644 --- a/android/guava-tests/test/com/google/common/base/SuppliersTest.java +++ b/android/guava-tests/test/com/google/common/base/SuppliersTest.java @@ -81,15 +81,16 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se private static final long serialVersionUID = 0L; } - static void checkMemoize(CountingSupplier countingSupplier, Supplier memoizedSupplier) { + static void checkMemoize(CountingSupplier countingSupplier, + Suppliers.MemoizingSupplier memoizedSupplier) { // the underlying supplier hasn't executed yet assertEquals(0, countingSupplier.calls); - + assertFalse(memoizedSupplier.isMemoized()); assertEquals(10, (int) memoizedSupplier.get()); // now it has assertEquals(1, countingSupplier.calls); - + assertTrue(memoizedSupplier.isMemoized()); assertEquals(10, (int) memoizedSupplier.get()); // it still should only have executed once due to memoization @@ -102,7 +103,7 @@ public void testMemoize() { } private void memoizeTest(CountingSupplier countingSupplier) { - Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); + Suppliers.MemoizingSupplier memoizedSupplier = Suppliers.memoize(countingSupplier); checkMemoize(countingSupplier, memoizedSupplier); } @@ -139,7 +140,7 @@ private void memoizeExceptionThrownTest(ThrowingSupplier throwingSupplier) { @GwtIncompatible // SerializableTester public void testMemoizeNonSerializable() throws Exception { CountingSupplier countingSupplier = new CountingSupplier(); - Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); + Suppliers.MemoizingSupplier memoizedSupplier = Suppliers.memoize(countingSupplier); assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)"); checkMemoize(countingSupplier, memoizedSupplier); // Calls to the original memoized supplier shouldn't affect its copy. @@ -156,7 +157,7 @@ public void testMemoizeNonSerializable() throws Exception { @GwtIncompatible // SerializableTester public void testMemoizeSerializable() throws Exception { SerializableCountingSupplier countingSupplier = new SerializableCountingSupplier(); - Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); + Suppliers.MemoizingSupplier memoizedSupplier = Suppliers.memoize(countingSupplier); assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)"); checkMemoize(countingSupplier, memoizedSupplier); // Calls to the original memoized supplier shouldn't affect its copy. @@ -164,11 +165,11 @@ public void testMemoizeSerializable() throws Exception { assertThat(memoizedSupplier.toString()) .isEqualTo("Suppliers.memoize()"); - Supplier copy = reserialize(memoizedSupplier); + Suppliers.MemoizingSupplier copy = reserialize(memoizedSupplier); Object unused2 = memoizedSupplier.get(); CountingSupplier countingCopy = - (CountingSupplier) ((Suppliers.MemoizingSupplier) copy).delegate; + (CountingSupplier) ((Suppliers.SerializableMemoizingSupplier) copy).delegate; checkMemoize(countingCopy, copy); } diff --git a/android/guava/src/com/google/common/base/Suppliers.java b/android/guava/src/com/google/common/base/Suppliers.java index 32b9fec0a92f..06b26b529bc4 100644 --- a/android/guava/src/com/google/common/base/Suppliers.java +++ b/android/guava/src/com/google/common/base/Suppliers.java @@ -108,18 +108,34 @@ public String toString() { *

If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is * returned directly. */ - public static Supplier memoize(Supplier delegate) { + public static MemoizingSupplier memoize(Supplier delegate) { if (delegate instanceof NonSerializableMemoizingSupplier - || delegate instanceof MemoizingSupplier) { - return delegate; + || delegate instanceof SerializableMemoizingSupplier) { + return (MemoizingSupplier) delegate; } return delegate instanceof Serializable - ? new MemoizingSupplier(delegate) + ? new SerializableMemoizingSupplier(delegate) : new NonSerializableMemoizingSupplier(delegate); } + /** + * A supplier that memoizes the result of the first call to {@link #get()} and returns the same + * result on subsequent calls to {@link #get()}. + * + * @author Alexey Pelykh + */ + @ElementTypesAreNonnullByDefault + public interface MemoizingSupplier extends Supplier { + /** + * Returns {@code true} if the supplier has been initialized, i.e. if the first call to + * {@link #get()} has been made or if the supplier has been explicitly initialized. + */ + boolean isMemoized(); + } + @VisibleForTesting - static class MemoizingSupplier implements Supplier, Serializable { + static class SerializableMemoizingSupplier + implements MemoizingSupplier, Serializable { private transient Object lock = new Object(); final Supplier delegate; @@ -128,7 +144,7 @@ static class MemoizingSupplier implements Supplier delegate) { + SerializableMemoizingSupplier(Supplier delegate) { this.delegate = checkNotNull(delegate); } @@ -152,6 +168,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isMemoized() { + return initialized; + } + @Override public String toString() { return "Suppliers.memoize(" @@ -170,7 +191,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE } @VisibleForTesting - static class NonSerializableMemoizingSupplier implements Supplier { + static class NonSerializableMemoizingSupplier + implements MemoizingSupplier { private final Object lock = new Object(); @SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object @@ -206,6 +228,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isMemoized() { + return delegate == SUCCESSFULLY_COMPUTED; + } + @Override public String toString() { Supplier delegate = this.delegate; diff --git a/guava-tests/test/com/google/common/base/SuppliersTest.java b/guava-tests/test/com/google/common/base/SuppliersTest.java index 10cd0b040e2a..4101f4a6b9c1 100644 --- a/guava-tests/test/com/google/common/base/SuppliersTest.java +++ b/guava-tests/test/com/google/common/base/SuppliersTest.java @@ -81,15 +81,16 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se private static final long serialVersionUID = 0L; } - static void checkMemoize(CountingSupplier countingSupplier, Supplier memoizedSupplier) { + static void checkMemoize(CountingSupplier countingSupplier, + Suppliers.MemoizingSupplier memoizedSupplier) { // the underlying supplier hasn't executed yet assertEquals(0, countingSupplier.calls); - + assertFalse(memoizedSupplier.isMemoized()); assertEquals(10, (int) memoizedSupplier.get()); // now it has assertEquals(1, countingSupplier.calls); - + assertTrue(memoizedSupplier.isMemoized()); assertEquals(10, (int) memoizedSupplier.get()); // it still should only have executed once due to memoization @@ -102,7 +103,7 @@ public void testMemoize() { } private void memoizeTest(CountingSupplier countingSupplier) { - Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); + Suppliers.MemoizingSupplier memoizedSupplier = Suppliers.memoize(countingSupplier); checkMemoize(countingSupplier, memoizedSupplier); } @@ -139,7 +140,7 @@ private void memoizeExceptionThrownTest(ThrowingSupplier throwingSupplier) { @GwtIncompatible // SerializableTester public void testMemoizeNonSerializable() throws Exception { CountingSupplier countingSupplier = new CountingSupplier(); - Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); + Suppliers.MemoizingSupplier memoizedSupplier = Suppliers.memoize(countingSupplier); assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)"); checkMemoize(countingSupplier, memoizedSupplier); // Calls to the original memoized supplier shouldn't affect its copy. @@ -156,7 +157,7 @@ public void testMemoizeNonSerializable() throws Exception { @GwtIncompatible // SerializableTester public void testMemoizeSerializable() throws Exception { SerializableCountingSupplier countingSupplier = new SerializableCountingSupplier(); - Supplier memoizedSupplier = Suppliers.memoize(countingSupplier); + Suppliers.MemoizingSupplier memoizedSupplier = Suppliers.memoize(countingSupplier); assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)"); checkMemoize(countingSupplier, memoizedSupplier); // Calls to the original memoized supplier shouldn't affect its copy. @@ -164,11 +165,11 @@ public void testMemoizeSerializable() throws Exception { assertThat(memoizedSupplier.toString()) .isEqualTo("Suppliers.memoize()"); - Supplier copy = reserialize(memoizedSupplier); + Suppliers.MemoizingSupplier copy = reserialize(memoizedSupplier); Object unused2 = memoizedSupplier.get(); CountingSupplier countingCopy = - (CountingSupplier) ((Suppliers.MemoizingSupplier) copy).delegate; + (CountingSupplier) ((Suppliers.SerializableMemoizingSupplier) copy).delegate; checkMemoize(countingCopy, copy); } diff --git a/guava/src/com/google/common/base/Suppliers.java b/guava/src/com/google/common/base/Suppliers.java index 32b9fec0a92f..06b26b529bc4 100644 --- a/guava/src/com/google/common/base/Suppliers.java +++ b/guava/src/com/google/common/base/Suppliers.java @@ -108,18 +108,34 @@ public String toString() { *

If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is * returned directly. */ - public static Supplier memoize(Supplier delegate) { + public static MemoizingSupplier memoize(Supplier delegate) { if (delegate instanceof NonSerializableMemoizingSupplier - || delegate instanceof MemoizingSupplier) { - return delegate; + || delegate instanceof SerializableMemoizingSupplier) { + return (MemoizingSupplier) delegate; } return delegate instanceof Serializable - ? new MemoizingSupplier(delegate) + ? new SerializableMemoizingSupplier(delegate) : new NonSerializableMemoizingSupplier(delegate); } + /** + * A supplier that memoizes the result of the first call to {@link #get()} and returns the same + * result on subsequent calls to {@link #get()}. + * + * @author Alexey Pelykh + */ + @ElementTypesAreNonnullByDefault + public interface MemoizingSupplier extends Supplier { + /** + * Returns {@code true} if the supplier has been initialized, i.e. if the first call to + * {@link #get()} has been made or if the supplier has been explicitly initialized. + */ + boolean isMemoized(); + } + @VisibleForTesting - static class MemoizingSupplier implements Supplier, Serializable { + static class SerializableMemoizingSupplier + implements MemoizingSupplier, Serializable { private transient Object lock = new Object(); final Supplier delegate; @@ -128,7 +144,7 @@ static class MemoizingSupplier implements Supplier delegate) { + SerializableMemoizingSupplier(Supplier delegate) { this.delegate = checkNotNull(delegate); } @@ -152,6 +168,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isMemoized() { + return initialized; + } + @Override public String toString() { return "Suppliers.memoize(" @@ -170,7 +191,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE } @VisibleForTesting - static class NonSerializableMemoizingSupplier implements Supplier { + static class NonSerializableMemoizingSupplier + implements MemoizingSupplier { private final Object lock = new Object(); @SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object @@ -206,6 +228,11 @@ public T get() { return uncheckedCastNullableTToT(value); } + @Override + public boolean isMemoized() { + return delegate == SUCCESSFULLY_COMPUTED; + } + @Override public String toString() { Supplier delegate = this.delegate;