• 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     @Override
get()66     public T get() {
67       return function.apply(supplier.get());
68     }
69     private static final long serialVersionUID = 0;
70   }
71 
72   /**
73    * Returns a supplier which caches the instance retrieved during the first
74    * call to {@code get()} and returns that value on subsequent calls to
75    * {@code get()}. See:
76    * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
77    *
78    * <p>The returned supplier is thread-safe. The supplier's serialized form
79    * does not contain the cached value, which will be recalculated when {@code
80    * get()} is called on the reserialized instance.
81    *
82    * <p>If {@code delegate} is an instance created by an earlier call to {@code
83    * memoize}, it is returned directly.
84    */
memoize(Supplier<T> delegate)85   public static <T> Supplier<T> memoize(Supplier<T> delegate) {
86     return (delegate instanceof MemoizingSupplier)
87         ? delegate
88         : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
89   }
90 
91   @VisibleForTesting
92   static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
93     final Supplier<T> delegate;
94     transient volatile boolean initialized;
95     // "value" does not need to be volatile; visibility piggy-backs
96     // on volatile read of "initialized".
97     transient T value;
98 
MemoizingSupplier(Supplier<T> delegate)99     MemoizingSupplier(Supplier<T> delegate) {
100       this.delegate = delegate;
101     }
102 
103     @Override
get()104     public T get() {
105       // A 2-field variant of Double Checked Locking.
106       if (!initialized) {
107         synchronized (this) {
108           if (!initialized) {
109             T t = delegate.get();
110             value = t;
111             initialized = true;
112             return t;
113           }
114         }
115       }
116       return value;
117     }
118 
119     private static final long serialVersionUID = 0;
120   }
121 
122   /**
123    * Returns a supplier that caches the instance supplied by the delegate and
124    * removes the cached value after the specified time has passed. Subsequent
125    * calls to {@code get()} return the cached value if the expiration time has
126    * not passed. After the expiration time, a new value is retrieved, cached,
127    * and returned. See:
128    * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
129    *
130    * <p>The returned supplier is thread-safe. The supplier's serialized form
131    * does not contain the cached value, which will be recalculated when {@code
132    * get()} is called on the reserialized instance.
133    *
134    * @param duration the length of time after a value is created that it
135    *     should stop being returned by subsequent {@code get()} calls
136    * @param unit the unit that {@code duration} is expressed in
137    * @throws IllegalArgumentException if {@code duration} is not positive
138    * @since 2.0
139    */
memoizeWithExpiration( Supplier<T> delegate, long duration, TimeUnit unit)140   public static <T> Supplier<T> memoizeWithExpiration(
141       Supplier<T> delegate, long duration, TimeUnit unit) {
142     return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
143   }
144 
145   @VisibleForTesting static class ExpiringMemoizingSupplier<T>
146       implements Supplier<T>, Serializable {
147     final Supplier<T> delegate;
148     final long durationNanos;
149     transient volatile T value;
150     // The special value 0 means "not yet initialized".
151     transient volatile long expirationNanos;
152 
ExpiringMemoizingSupplier( Supplier<T> delegate, long duration, TimeUnit unit)153     ExpiringMemoizingSupplier(
154         Supplier<T> delegate, long duration, TimeUnit unit) {
155       this.delegate = Preconditions.checkNotNull(delegate);
156       this.durationNanos = unit.toNanos(duration);
157       Preconditions.checkArgument(duration > 0);
158     }
159 
160     @Override
get()161     public T get() {
162       // Another variant of Double Checked Locking.
163       //
164       // We use two volatile reads.  We could reduce this to one by
165       // putting our fields into a holder class, but (at least on x86)
166       // the extra memory consumption and indirection are more
167       // expensive than the extra volatile reads.
168       long nanos = expirationNanos;
169       long now = Platform.systemNanoTime();
170       if (nanos == 0 || now - nanos >= 0) {
171         synchronized (this) {
172           if (nanos == expirationNanos) {  // recheck for lost race
173             T t = delegate.get();
174             value = t;
175             nanos = now + durationNanos;
176             // In the very unlikely event that nanos is 0, set it to 1;
177             // no one will notice 1 ns of tardiness.
178             expirationNanos = (nanos == 0) ? 1 : nanos;
179             return t;
180           }
181         }
182       }
183       return value;
184     }
185 
186     private static final long serialVersionUID = 0;
187   }
188 
189   /**
190    * Returns a supplier that always supplies {@code instance}.
191    */
ofInstance(@ullable T instance)192   public static <T> Supplier<T> ofInstance(@Nullable T instance) {
193     return new SupplierOfInstance<T>(instance);
194   }
195 
196   private static class SupplierOfInstance<T>
197       implements Supplier<T>, Serializable {
198     final T instance;
199 
SupplierOfInstance(@ullable T instance)200     SupplierOfInstance(@Nullable T instance) {
201       this.instance = instance;
202     }
203     @Override
get()204     public T get() {
205       return instance;
206     }
207     private static final long serialVersionUID = 0;
208   }
209 
210   /**
211    * Returns a supplier whose {@code get()} method synchronizes on
212    * {@code delegate} before calling it, making it thread-safe.
213    */
synchronizedSupplier(Supplier<T> delegate)214   public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
215     return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
216   }
217 
218   private static class ThreadSafeSupplier<T>
219       implements Supplier<T>, Serializable {
220     final Supplier<T> delegate;
221 
ThreadSafeSupplier(Supplier<T> delegate)222     ThreadSafeSupplier(Supplier<T> delegate) {
223       this.delegate = delegate;
224     }
225     @Override
get()226     public T get() {
227       synchronized (delegate) {
228         return delegate.get();
229       }
230     }
231     private static final long serialVersionUID = 0;
232   }
233 
234   /**
235    * Returns a function that accepts a supplier and returns the result of
236    * invoking {@link Supplier#get} on that supplier.
237    *
238    * @since 8.0
239    */
240   @Beta
241   @SuppressWarnings("unchecked") // SupplierFunction works for any T.
supplierFunction()242   public static <T> Function<Supplier<T>, T> supplierFunction() {
243     return (Function) SupplierFunction.INSTANCE;
244   }
245 
246   private enum SupplierFunction implements Function<Supplier<?>, Object> {
247     INSTANCE;
248 
249     @Override
apply(Supplier<?> input)250     public Object apply(Supplier<?> input) {
251       return input.get();
252     }
253   }
254 }
255