• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
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  * Useful suppliers.
30  *
31  * <p>All methods return serializable suppliers as long as they're given
32  * serializable parameters.
33  *
34  * @author Laurence Gonsalves
35  * @author Harry Heymann
36  * @since 2.0 (imported from Google Collections Library)
37  */
38 @GwtCompatible
39 public final class Suppliers {
Suppliers()40   private Suppliers() {}
41 
42   /**
43    * Returns a new supplier which is the composition of the provided function
44    * and supplier. In other words, the new supplier's value will be computed by
45    * retrieving the value from {@code supplier}, and then applying
46    * {@code function} to that value. Note that the resulting supplier will not
47    * call {@code supplier} or invoke {@code function} until it is called.
48    */
compose( Function<? super F, T> function, Supplier<F> supplier)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 
SupplierComposition(Function<? super F, T> function, Supplier<F> supplier)61     SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
62       this.function = function;
63       this.supplier = supplier;
64     }
65 
get()66     @Override public T get() {
67       return function.apply(supplier.get());
68     }
69 
equals(@ullable Object obj)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 
hashCode()78     @Override public int hashCode() {
79       return Objects.hashCode(function, supplier);
80     }
81 
toString()82     @Override public String toString() {
83       return "Suppliers.compose(" + function + ", " + supplier + ")";
84     }
85 
86     private static final long serialVersionUID = 0;
87   }
88 
89   /**
90    * Returns a supplier which caches the instance retrieved during the first
91    * call to {@code get()} and returns that value on subsequent calls to
92    * {@code get()}. See:
93    * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
94    *
95    * <p>The returned supplier is thread-safe. The supplier's serialized form
96    * does not contain the cached value, which will be recalculated when {@code
97    * get()} is called on the reserialized instance.
98    *
99    * <p>If {@code delegate} is an instance created by an earlier call to {@code
100    * memoize}, it is returned directly.
101    */
memoize(Supplier<T> delegate)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     // "value" does not need to be volatile; visibility piggy-backs
113     // on volatile read of "initialized".
114     transient T value;
115 
MemoizingSupplier(Supplier<T> delegate)116     MemoizingSupplier(Supplier<T> delegate) {
117       this.delegate = delegate;
118     }
119 
get()120     @Override public T get() {
121       // A 2-field variant of Double Checked Locking.
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 
toString()135     @Override public String toString() {
136       return "Suppliers.memoize(" + delegate + ")";
137     }
138 
139     private static final long serialVersionUID = 0;
140   }
141 
142   /**
143    * Returns a supplier that caches the instance supplied by the delegate and
144    * removes the cached value after the specified time has passed. Subsequent
145    * calls to {@code get()} return the cached value if the expiration time has
146    * not passed. After the expiration time, a new value is retrieved, cached,
147    * and returned. See:
148    * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
149    *
150    * <p>The returned supplier is thread-safe. The supplier's serialized form
151    * does not contain the cached value, which will be recalculated when {@code
152    * get()} is called on the reserialized instance.
153    *
154    * @param duration the length of time after a value is created that it
155    *     should stop being returned by subsequent {@code get()} calls
156    * @param unit the unit that {@code duration} is expressed in
157    * @throws IllegalArgumentException if {@code duration} is not positive
158    * @since 2.0
159    */
memoizeWithExpiration( Supplier<T> delegate, long duration, TimeUnit unit)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     // The special value 0 means "not yet initialized".
171     transient volatile long expirationNanos;
172 
ExpiringMemoizingSupplier( Supplier<T> delegate, long duration, TimeUnit unit)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 
get()180     @Override public T get() {
181       // Another variant of Double Checked Locking.
182       //
183       // We use two volatile reads.  We could reduce this to one by
184       // putting our fields into a holder class, but (at least on x86)
185       // the extra memory consumption and indirection are more
186       // expensive than the extra volatile reads.
187       long nanos = expirationNanos;
188       long now = Platform.systemNanoTime();
189       if (nanos == 0 || now - nanos >= 0) {
190         synchronized (this) {
191           if (nanos == expirationNanos) {  // recheck for lost race
192             T t = delegate.get();
193             value = t;
194             nanos = now + durationNanos;
195             // In the very unlikely event that nanos is 0, set it to 1;
196             // no one will notice 1 ns of tardiness.
197             expirationNanos = (nanos == 0) ? 1 : nanos;
198             return t;
199           }
200         }
201       }
202       return value;
203     }
204 
toString()205     @Override public String toString() {
206       // This is a little strange if the unit the user provided was not NANOS,
207       // but we don't want to store the unit just for toString
208       return "Suppliers.memoizeWithExpiration(" + delegate + ", " +
209           durationNanos + ", NANOS)";
210     }
211 
212     private static final long serialVersionUID = 0;
213   }
214 
215   /**
216    * Returns a supplier that always supplies {@code instance}.
217    */
ofInstance(@ullable T instance)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 
SupplierOfInstance(@ullable T instance)226     SupplierOfInstance(@Nullable T instance) {
227       this.instance = instance;
228     }
229 
get()230     @Override public T get() {
231       return instance;
232     }
233 
equals(@ullable Object obj)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 
hashCode()242     @Override public int hashCode() {
243       return Objects.hashCode(instance);
244     }
245 
toString()246     @Override public String toString() {
247       return "Suppliers.ofInstance(" + instance + ")";
248     }
249 
250     private static final long serialVersionUID = 0;
251   }
252 
253   /**
254    * Returns a supplier whose {@code get()} method synchronizes on
255    * {@code delegate} before calling it, making it thread-safe.
256    */
synchronizedSupplier(Supplier<T> delegate)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 
ThreadSafeSupplier(Supplier<T> delegate)265     ThreadSafeSupplier(Supplier<T> delegate) {
266       this.delegate = delegate;
267     }
268 
get()269     @Override public T get() {
270       synchronized (delegate) {
271         return delegate.get();
272       }
273     }
274 
toString()275     @Override public String toString() {
276       return "Suppliers.synchronizedSupplier(" + delegate + ")";
277     }
278 
279     private static final long serialVersionUID = 0;
280   }
281 
282   /**
283    * Returns a function that accepts a supplier and returns the result of
284    * invoking {@link Supplier#get} on that supplier.
285    *
286    * @since 8.0
287    */
288   @Beta
supplierFunction()289   public static <T> Function<Supplier<T>, T> supplierFunction() {
290     @SuppressWarnings("unchecked") // implementation is "fully variant"
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     // Note: This makes T a "pass-through type"
apply(Supplier<Object> input)301     @Override public Object apply(Supplier<Object> input) {
302       return input.get();
303     }
304 
toString()305     @Override public String toString() {
306       return "Suppliers.supplierFunction()";
307     }
308   }
309 }
310