Skip to content

Commit 56ac6ff

Browse files
committed
(feat) MemoizingSupplier.isMemoized
1 parent d1a3cd5 commit 56ac6ff

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
@@ -81,15 +81,16 @@ static class SerializableThrowingSupplier extends ThrowingSupplier implements Se
8181
private static final long serialVersionUID = 0L;
8282
}
8383

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

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

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

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

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

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

170171
CountingSupplier countingCopy =
171-
(CountingSupplier) ((Suppliers.MemoizingSupplier<Integer>) copy).delegate;
172+
(CountingSupplier) ((Suppliers.SerializableMemoizingSupplier<Integer>) copy).delegate;
172173
checkMemoize(countingCopy, copy);
173174
}
174175

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

+34-7
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,34 @@ public String toString() {
108108
* <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
109109
* returned directly.
110110
*/
111-
public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) {
111+
public static <T extends @Nullable Object> MemoizingSupplier<T> memoize(Supplier<T> delegate) {
112112
if (delegate instanceof NonSerializableMemoizingSupplier
113-
|| delegate instanceof MemoizingSupplier) {
114-
return delegate;
113+
|| delegate instanceof SerializableMemoizingSupplier) {
114+
return (MemoizingSupplier<T>) delegate;
115115
}
116116
return delegate instanceof Serializable
117-
? new MemoizingSupplier<T>(delegate)
117+
? new SerializableMemoizingSupplier<T>(delegate)
118118
: new NonSerializableMemoizingSupplier<T>(delegate);
119119
}
120120

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

125141
final Supplier<T> delegate;
@@ -128,7 +144,7 @@ static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T
128144
// on volatile read of "initialized".
129145
transient @Nullable T value;
130146

131-
MemoizingSupplier(Supplier<T> delegate) {
147+
SerializableMemoizingSupplier(Supplier<T> delegate) {
132148
this.delegate = checkNotNull(delegate);
133149
}
134150

@@ -152,6 +168,11 @@ public T get() {
152168
return uncheckedCastNullableTToT(value);
153169
}
154170

171+
@Override
172+
public boolean isMemoized() {
173+
return initialized;
174+
}
175+
155176
@Override
156177
public String toString() {
157178
return "Suppliers.memoize("
@@ -170,7 +191,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
170191
}
171192

172193
@VisibleForTesting
173-
static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> {
194+
static class NonSerializableMemoizingSupplier<T extends @Nullable Object>
195+
implements MemoizingSupplier<T> {
174196
private final Object lock = new Object();
175197

176198
@SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object
@@ -206,6 +228,11 @@ public T get() {
206228
return uncheckedCastNullableTToT(value);
207229
}
208230

231+
@Override
232+
public boolean isMemoized() {
233+
return delegate == SUCCESSFULLY_COMPUTED;
234+
}
235+
209236
@Override
210237
public String toString() {
211238
Supplier<T> delegate = this.delegate;

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

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

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

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

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

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

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

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

170171
CountingSupplier countingCopy =
171-
(CountingSupplier) ((Suppliers.MemoizingSupplier<Integer>) copy).delegate;
172+
(CountingSupplier) ((Suppliers.SerializableMemoizingSupplier<Integer>) copy).delegate;
172173
checkMemoize(countingCopy, copy);
173174
}
174175

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

+34-7
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,34 @@ public String toString() {
108108
* <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
109109
* returned directly.
110110
*/
111-
public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) {
111+
public static <T extends @Nullable Object> MemoizingSupplier<T> memoize(Supplier<T> delegate) {
112112
if (delegate instanceof NonSerializableMemoizingSupplier
113-
|| delegate instanceof MemoizingSupplier) {
114-
return delegate;
113+
|| delegate instanceof SerializableMemoizingSupplier) {
114+
return (MemoizingSupplier<T>) delegate;
115115
}
116116
return delegate instanceof Serializable
117-
? new MemoizingSupplier<T>(delegate)
117+
? new SerializableMemoizingSupplier<T>(delegate)
118118
: new NonSerializableMemoizingSupplier<T>(delegate);
119119
}
120120

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

125141
final Supplier<T> delegate;
@@ -128,7 +144,7 @@ static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T
128144
// on volatile read of "initialized".
129145
transient @Nullable T value;
130146

131-
MemoizingSupplier(Supplier<T> delegate) {
147+
SerializableMemoizingSupplier(Supplier<T> delegate) {
132148
this.delegate = checkNotNull(delegate);
133149
}
134150

@@ -152,6 +168,11 @@ public T get() {
152168
return uncheckedCastNullableTToT(value);
153169
}
154170

171+
@Override
172+
public boolean isMemoized() {
173+
return initialized;
174+
}
175+
155176
@Override
156177
public String toString() {
157178
return "Suppliers.memoize("
@@ -170,7 +191,8 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE
170191
}
171192

172193
@VisibleForTesting
173-
static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> {
194+
static class NonSerializableMemoizingSupplier<T extends @Nullable Object>
195+
implements MemoizingSupplier<T> {
174196
private final Object lock = new Object();
175197

176198
@SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object
@@ -206,6 +228,11 @@ public T get() {
206228
return uncheckedCastNullableTToT(value);
207229
}
208230

231+
@Override
232+
public boolean isMemoized() {
233+
return delegate == SUCCESSFULLY_COMPUTED;
234+
}
235+
209236
@Override
210237
public String toString() {
211238
Supplier<T> delegate = this.delegate;

0 commit comments

Comments
 (0)