1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.base;
18
19 import com.google.common.annotations.Beta;
20 import com.google.common.annotations.GwtCompatible;
21 import com.google.common.annotations.VisibleForTesting;
22
23 import java.io.Serializable;
24 import java.util.concurrent.TimeUnit;
25
26 import javax.annotation.Nullable;
27
28
29
30
31
32
33
34
35
36
37
38 @GwtCompatible
39 public final class Suppliers {
40 private Suppliers() {}
41
42
43
44
45
46
47
48
49 public static <F, T> Supplier<T> compose(
50 Function<? super F, T> function, Supplier<F> supplier) {
51 Preconditions.checkNotNull(function);
52 Preconditions.checkNotNull(supplier);
53 return new SupplierComposition<F, T>(function, supplier);
54 }
55
56 private static class SupplierComposition<F, T>
57 implements Supplier<T>, Serializable {
58 final Function<? super F, T> function;
59 final Supplier<F> supplier;
60
61 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
62 this.function = function;
63 this.supplier = supplier;
64 }
65
66 @Override public T get() {
67 return function.apply(supplier.get());
68 }
69
70 @Override public boolean equals(@Nullable Object obj) {
71 if (obj instanceof SupplierComposition) {
72 SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
73 return function.equals(that.function) && supplier.equals(that.supplier);
74 }
75 return false;
76 }
77
78 @Override public int hashCode() {
79 return Objects.hashCode(function, supplier);
80 }
81
82 @Override public String toString() {
83 return "Suppliers.compose(" + function + ", " + supplier + ")";
84 }
85
86 private static final long serialVersionUID = 0;
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 public static <T> Supplier<T> memoize(Supplier<T> delegate) {
103 return (delegate instanceof MemoizingSupplier)
104 ? delegate
105 : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
106 }
107
108 @VisibleForTesting
109 static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
110 final Supplier<T> delegate;
111 transient volatile boolean initialized;
112
113
114 transient T value;
115
116 MemoizingSupplier(Supplier<T> delegate) {
117 this.delegate = delegate;
118 }
119
120 @Override public T get() {
121
122 if (!initialized) {
123 synchronized (this) {
124 if (!initialized) {
125 T t = delegate.get();
126 value = t;
127 initialized = true;
128 return t;
129 }
130 }
131 }
132 return value;
133 }
134
135 @Override public String toString() {
136 return "Suppliers.memoize(" + delegate + ")";
137 }
138
139 private static final long serialVersionUID = 0;
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160 public static <T> Supplier<T> memoizeWithExpiration(
161 Supplier<T> delegate, long duration, TimeUnit unit) {
162 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
163 }
164
165 @VisibleForTesting static class ExpiringMemoizingSupplier<T>
166 implements Supplier<T>, Serializable {
167 final Supplier<T> delegate;
168 final long durationNanos;
169 transient volatile T value;
170
171 transient volatile long expirationNanos;
172
173 ExpiringMemoizingSupplier(
174 Supplier<T> delegate, long duration, TimeUnit unit) {
175 this.delegate = Preconditions.checkNotNull(delegate);
176 this.durationNanos = unit.toNanos(duration);
177 Preconditions.checkArgument(duration > 0);
178 }
179
180 @Override public T get() {
181
182
183
184
185
186
187 long nanos = expirationNanos;
188 long now = Platform.systemNanoTime();
189 if (nanos == 0 || now - nanos >= 0) {
190 synchronized (this) {
191 if (nanos == expirationNanos) {
192 T t = delegate.get();
193 value = t;
194 nanos = now + durationNanos;
195
196
197 expirationNanos = (nanos == 0) ? 1 : nanos;
198 return t;
199 }
200 }
201 }
202 return value;
203 }
204
205 @Override public String toString() {
206
207
208 return "Suppliers.memoizeWithExpiration(" + delegate + ", " +
209 durationNanos + ", NANOS)";
210 }
211
212 private static final long serialVersionUID = 0;
213 }
214
215
216
217
218 public static <T> Supplier<T> ofInstance(@Nullable T instance) {
219 return new SupplierOfInstance<T>(instance);
220 }
221
222 private static class SupplierOfInstance<T>
223 implements Supplier<T>, Serializable {
224 final T instance;
225
226 SupplierOfInstance(@Nullable T instance) {
227 this.instance = instance;
228 }
229
230 @Override public T get() {
231 return instance;
232 }
233
234 @Override public boolean equals(@Nullable Object obj) {
235 if (obj instanceof SupplierOfInstance) {
236 SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
237 return Objects.equal(instance, that.instance);
238 }
239 return false;
240 }
241
242 @Override public int hashCode() {
243 return Objects.hashCode(instance);
244 }
245
246 @Override public String toString() {
247 return "Suppliers.ofInstance(" + instance + ")";
248 }
249
250 private static final long serialVersionUID = 0;
251 }
252
253
254
255
256
257 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
258 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
259 }
260
261 private static class ThreadSafeSupplier<T>
262 implements Supplier<T>, Serializable {
263 final Supplier<T> delegate;
264
265 ThreadSafeSupplier(Supplier<T> delegate) {
266 this.delegate = delegate;
267 }
268
269 @Override public T get() {
270 synchronized (delegate) {
271 return delegate.get();
272 }
273 }
274
275 @Override public String toString() {
276 return "Suppliers.synchronizedSupplier(" + delegate + ")";
277 }
278
279 private static final long serialVersionUID = 0;
280 }
281
282
283
284
285
286
287
288 @Beta
289 public static <T> Function<Supplier<T>, T> supplierFunction() {
290 @SuppressWarnings("unchecked")
291 SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
292 return sf;
293 }
294
295 private interface SupplierFunction<T> extends Function<Supplier<T>, T> {}
296
297 private enum SupplierFunctionImpl implements SupplierFunction<Object> {
298 INSTANCE;
299
300
301 @Override public Object apply(Supplier<Object> input) {
302 return input.get();
303 }
304
305 @Override public String toString() {
306 return "Suppliers.supplierFunction()";
307 }
308 }
309 }