Skip to content

Commit bb13e7a

Browse files
committed
(feat) MemoizingSupplier.isInitialized
1 parent fea7a36 commit bb13e7a

File tree

4 files changed

+86
-30
lines changed

4 files changed

+86
-30
lines changed

android/guava-tests/test/com/google/common/base/SuppliersTest.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,16 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se
8080
private static final long serialVersionUID = 0L;
8181
}
8282

83-
static void checkMemoize(CountingSupplier countingSupplier, Supplier<Integer> memoizedSupplier) {
83+
static void checkMemoize(CountingSupplier countingSupplier,
84+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier) {
8485
// the underlying supplier hasn't executed yet
8586
assertEquals(0, countingSupplier.calls);
86-
87+
assertFalse(memoizedSupplier.isMemoized());
8788
assertEquals(10, (int) memoizedSupplier.get());
8889

8990
// now it has
9091
assertEquals(1, countingSupplier.calls);
91-
92+
assertTrue(memoizedSupplier.isMemoized());
9293
assertEquals(10, (int) memoizedSupplier.get());
9394

9495
// it still should only have executed once due to memoization
@@ -101,7 +102,7 @@ public void testMemoize() {
101102
}
102103

103104
private void memoizeTest(CountingSupplier countingSupplier) {
104-
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
105+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
105106
checkMemoize(countingSupplier, memoizedSupplier);
106107
}
107108

@@ -138,7 +139,7 @@ private void memoizeExceptionThrownTest(ThrowingSupplier throwingSupplier) {
138139
@GwtIncompatible // SerializableTester
139140
public void testMemoizeNonSerializable() throws Exception {
140141
CountingSupplier countingSupplier = new CountingSupplier();
141-
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
142+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
142143
assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)");
143144
checkMemoize(countingSupplier, memoizedSupplier);
144145
// Calls to the original memoized supplier shouldn't affect its copy.
@@ -155,19 +156,19 @@ public void testMemoizeNonSerializable() throws Exception {
155156
@GwtIncompatible // SerializableTester
156157
public void testMemoizeSerializable() throws Exception {
157158
SerializableCountingSupplier countingSupplier = new SerializableCountingSupplier();
158-
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
159+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
159160
assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)");
160161
checkMemoize(countingSupplier, memoizedSupplier);
161162
// Calls to the original memoized supplier shouldn't affect its copy.
162163
Object unused = memoizedSupplier.get();
163164
assertThat(memoizedSupplier.toString())
164165
.isEqualTo("Suppliers.memoize(<supplier that returned 10>)");
165166

166-
Supplier<Integer> copy = reserialize(memoizedSupplier);
167+
Suppliers.MemoizingSupplier<Integer> copy = reserialize(memoizedSupplier);
167168
Object unused2 = memoizedSupplier.get();
168169

169170
CountingSupplier countingCopy =
170-
(CountingSupplier) ((Suppliers.MemoizingSupplier<Integer>) copy).delegate;
171+
(CountingSupplier) ((Suppliers.SerializableMemoizingSupplier<Integer>) copy).delegate;
171172
checkMemoize(countingCopy, copy);
172173
}
173174

android/guava/src/com/google/common/base/Suppliers.java

+34-7
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,34 @@ public String toString() {
110110
* <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
111111
* returned directly.
112112
*/
113-
public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) {
113+
public static <T extends @Nullable Object> MemoizingSupplier<T> memoize(Supplier<T> delegate) {
114114
if (delegate instanceof NonSerializableMemoizingSupplier
115-
|| delegate instanceof MemoizingSupplier) {
116-
return delegate;
115+
|| delegate instanceof SerializableMemoizingSupplier) {
116+
return (MemoizingSupplier<T>) delegate;
117117
}
118118
return delegate instanceof Serializable
119-
? new MemoizingSupplier<T>(delegate)
119+
? new SerializableMemoizingSupplier<T>(delegate)
120120
: new NonSerializableMemoizingSupplier<T>(delegate);
121121
}
122122

123+
/**
124+
* A supplier that memoizes the result of the first call to {@link #get()} and returns the same
125+
* result on subsequent calls to {@link #get()}.
126+
*
127+
* @author Alexey Pelykh
128+
*/
129+
@ElementTypesAreNonnullByDefault
130+
public interface MemoizingSupplier<T extends @Nullable Object> extends Supplier<T> {
131+
/**
132+
* Returns {@code true} if the supplier has been initialized, i.e. if the first call to
133+
* {@link #get()} has been made or if the supplier has been explicitly initialized.
134+
*/
135+
boolean isMemoized();
136+
}
137+
123138
@VisibleForTesting
124-
static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T>, Serializable {
139+
static class SerializableMemoizingSupplier<T extends @Nullable Object>
140+
implements MemoizingSupplier<T>, Serializable {
125141
private transient Object lock = new Object();
126142

127143
final Supplier<T> delegate;
@@ -130,7 +146,7 @@ static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T
130146
// on volatile read of "initialized".
131147
@CheckForNull transient T value;
132148

133-
MemoizingSupplier(Supplier<T> delegate) {
149+
SerializableMemoizingSupplier(Supplier<T> delegate) {
134150
this.delegate = checkNotNull(delegate);
135151
}
136152

@@ -154,6 +170,11 @@ public T get() {
154170
return uncheckedCastNullableTToT(value);
155171
}
156172

173+
@Override
174+
public boolean isMemoized() {
175+
return initialized;
176+
}
177+
157178
@Override
158179
public String toString() {
159180
return "Suppliers.memoize("
@@ -172,7 +193,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
172193
}
173194

174195
@VisibleForTesting
175-
static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> {
196+
static class NonSerializableMemoizingSupplier<T extends @Nullable Object>
197+
implements MemoizingSupplier<T> {
176198
private final Object lock = new Object();
177199

178200
@SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object
@@ -208,6 +230,11 @@ public T get() {
208230
return uncheckedCastNullableTToT(value);
209231
}
210232

233+
@Override
234+
public boolean isMemoized() {
235+
return delegate == SUCCESSFULLY_COMPUTED;
236+
}
237+
211238
@Override
212239
public String toString() {
213240
Supplier<T> delegate = this.delegate;

guava-tests/test/com/google/common/base/SuppliersTest.java

+9-8
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,16 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se
8080
private static final long serialVersionUID = 0L;
8181
}
8282

83-
static void checkMemoize(CountingSupplier countingSupplier, Supplier<Integer> memoizedSupplier) {
83+
static void checkMemoize(CountingSupplier countingSupplier,
84+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier) {
8485
// the underlying supplier hasn't executed yet
8586
assertEquals(0, countingSupplier.calls);
86-
87+
assertFalse(memoizedSupplier.isMemoized());
8788
assertEquals(10, (int) memoizedSupplier.get());
8889

8990
// now it has
9091
assertEquals(1, countingSupplier.calls);
91-
92+
assertTrue(memoizedSupplier.isMemoized());
9293
assertEquals(10, (int) memoizedSupplier.get());
9394

9495
// it still should only have executed once due to memoization
@@ -101,7 +102,7 @@ public void testMemoize() {
101102
}
102103

103104
private void memoizeTest(CountingSupplier countingSupplier) {
104-
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
105+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
105106
checkMemoize(countingSupplier, memoizedSupplier);
106107
}
107108

@@ -138,7 +139,7 @@ private void memoizeExceptionThrownTest(ThrowingSupplier throwingSupplier) {
138139
@GwtIncompatible // SerializableTester
139140
public void testMemoizeNonSerializable() throws Exception {
140141
CountingSupplier countingSupplier = new CountingSupplier();
141-
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
142+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
142143
assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)");
143144
checkMemoize(countingSupplier, memoizedSupplier);
144145
// Calls to the original memoized supplier shouldn't affect its copy.
@@ -155,19 +156,19 @@ public void testMemoizeNonSerializable() throws Exception {
155156
@GwtIncompatible // SerializableTester
156157
public void testMemoizeSerializable() throws Exception {
157158
SerializableCountingSupplier countingSupplier = new SerializableCountingSupplier();
158-
Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
159+
Suppliers.MemoizingSupplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
159160
assertThat(memoizedSupplier.toString()).isEqualTo("Suppliers.memoize(CountingSupplier)");
160161
checkMemoize(countingSupplier, memoizedSupplier);
161162
// Calls to the original memoized supplier shouldn't affect its copy.
162163
Object unused = memoizedSupplier.get();
163164
assertThat(memoizedSupplier.toString())
164165
.isEqualTo("Suppliers.memoize(<supplier that returned 10>)");
165166

166-
Supplier<Integer> copy = reserialize(memoizedSupplier);
167+
Suppliers.MemoizingSupplier<Integer> copy = reserialize(memoizedSupplier);
167168
Object unused2 = memoizedSupplier.get();
168169

169170
CountingSupplier countingCopy =
170-
(CountingSupplier) ((Suppliers.MemoizingSupplier<Integer>) copy).delegate;
171+
(CountingSupplier) ((Suppliers.SerializableMemoizingSupplier<Integer>) copy).delegate;
171172
checkMemoize(countingCopy, copy);
172173
}
173174

guava/src/com/google/common/base/Suppliers.java

+34-7
Original file line numberDiff line numberDiff line change
@@ -110,18 +110,34 @@ public String toString() {
110110
* <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
111111
* returned directly.
112112
*/
113-
public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) {
113+
public static <T extends @Nullable Object> MemoizingSupplier<T> memoize(Supplier<T> delegate) {
114114
if (delegate instanceof NonSerializableMemoizingSupplier
115-
|| delegate instanceof MemoizingSupplier) {
116-
return delegate;
115+
|| delegate instanceof SerializableMemoizingSupplier) {
116+
return (MemoizingSupplier<T>) delegate;
117117
}
118118
return delegate instanceof Serializable
119-
? new MemoizingSupplier<T>(delegate)
119+
? new SerializableMemoizingSupplier<T>(delegate)
120120
: new NonSerializableMemoizingSupplier<T>(delegate);
121121
}
122122

123+
/**
124+
* A supplier that memoizes the result of the first call to {@link #get()} and returns the same
125+
* result on subsequent calls to {@link #get()}.
126+
*
127+
* @author Alexey Pelykh
128+
*/
129+
@ElementTypesAreNonnullByDefault
130+
public interface MemoizingSupplier<T extends @Nullable Object> extends Supplier<T> {
131+
/**
132+
* Returns {@code true} if the supplier has been initialized, i.e. if the first call to
133+
* {@link #get()} has been made or if the supplier has been explicitly initialized.
134+
*/
135+
boolean isMemoized();
136+
}
137+
123138
@VisibleForTesting
124-
static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T>, Serializable {
139+
static class SerializableMemoizingSupplier<T extends @Nullable Object>
140+
implements MemoizingSupplier<T>, Serializable {
125141
private transient Object lock = new Object();
126142

127143
final Supplier<T> delegate;
@@ -130,7 +146,7 @@ static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T
130146
// on volatile read of "initialized".
131147
@CheckForNull transient T value;
132148

133-
MemoizingSupplier(Supplier<T> delegate) {
149+
SerializableMemoizingSupplier(Supplier<T> delegate) {
134150
this.delegate = checkNotNull(delegate);
135151
}
136152

@@ -154,6 +170,11 @@ public T get() {
154170
return uncheckedCastNullableTToT(value);
155171
}
156172

173+
@Override
174+
public boolean isMemoized() {
175+
return initialized;
176+
}
177+
157178
@Override
158179
public String toString() {
159180
return "Suppliers.memoize("
@@ -172,7 +193,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
172193
}
173194

174195
@VisibleForTesting
175-
static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> {
196+
static class NonSerializableMemoizingSupplier<T extends @Nullable Object>
197+
implements MemoizingSupplier<T> {
176198
private final Object lock = new Object();
177199

178200
@SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object
@@ -208,6 +230,11 @@ public T get() {
208230
return uncheckedCastNullableTToT(value);
209231
}
210232

233+
@Override
234+
public boolean isMemoized() {
235+
return delegate == SUCCESSFULLY_COMPUTED;
236+
}
237+
211238
@Override
212239
public String toString() {
213240
Supplier<T> delegate = this.delegate;

0 commit comments

Comments
 (0)