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
17package com.google.common.base;
18
19import com.google.common.annotations.Beta;
20import com.google.common.annotations.GwtCompatible;
21import com.google.common.annotations.VisibleForTesting;
22
23import java.io.Serializable;
24import java.util.concurrent.TimeUnit;
25
26import 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
39public final class 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   */
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   * 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   */
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
116    MemoizingSupplier(Supplier<T> delegate) {
117      this.delegate = delegate;
118    }
119
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
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   */
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
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      // 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
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   */
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   * Returns a supplier whose {@code get()} method synchronizes on
255   * {@code delegate} before calling it, making it thread-safe.
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   * 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
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"
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}
310