001/*
002 * Copyright (C) 2007 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.base;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019
020import com.google.common.annotations.GwtCompatible;
021import com.google.common.annotations.VisibleForTesting;
022import java.io.Serializable;
023import java.util.concurrent.TimeUnit;
024import org.checkerframework.checker.nullness.compatqual.NullableDecl;
025
026/**
027 * Useful suppliers.
028 *
029 * <p>All methods return serializable suppliers as long as they're given serializable parameters.
030 *
031 * @author Laurence Gonsalves
032 * @author Harry Heymann
033 * @since 2.0
034 */
035@GwtCompatible
036public final class Suppliers {
037  private Suppliers() {}
038
039  /**
040   * Returns a new supplier which is the composition of the provided function and supplier. In other
041   * words, the new supplier's value will be computed by retrieving the value from {@code supplier},
042   * and then applying {@code function} to that value. Note that the resulting supplier will not
043   * call {@code supplier} or invoke {@code function} until it is called.
044   */
045  public static <F, T> Supplier<T> compose(Function<? super F, T> function, Supplier<F> supplier) {
046    return new SupplierComposition<>(function, supplier);
047  }
048
049  private static class SupplierComposition<F, T> implements Supplier<T>, Serializable {
050    final Function<? super F, T> function;
051    final Supplier<F> supplier;
052
053    SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
054      this.function = checkNotNull(function);
055      this.supplier = checkNotNull(supplier);
056    }
057
058    @Override
059    public T get() {
060      return function.apply(supplier.get());
061    }
062
063    @Override
064    public boolean equals(@NullableDecl Object obj) {
065      if (obj instanceof SupplierComposition) {
066        SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
067        return function.equals(that.function) && supplier.equals(that.supplier);
068      }
069      return false;
070    }
071
072    @Override
073    public int hashCode() {
074      return Objects.hashCode(function, supplier);
075    }
076
077    @Override
078    public String toString() {
079      return "Suppliers.compose(" + function + ", " + supplier + ")";
080    }
081
082    private static final long serialVersionUID = 0;
083  }
084
085  /**
086   * Returns a supplier which caches the instance retrieved during the first call to {@code get()}
087   * and returns that value on subsequent calls to {@code get()}. See: <a
088   * href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
089   *
090   * <p>The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at
091   * most once unless the underlying {@code get()} throws an exception. The supplier's serialized
092   * form does not contain the cached value, which will be recalculated when {@code get()} is called
093   * on the reserialized instance.
094   *
095   * <p>When the underlying delegate throws an exception then this memoizing supplier will keep
096   * delegating calls until it returns valid data.
097   *
098   * <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
099   * returned directly.
100   */
101  public static <T> Supplier<T> memoize(Supplier<T> delegate) {
102    if (delegate instanceof NonSerializableMemoizingSupplier
103        || delegate instanceof MemoizingSupplier) {
104      return delegate;
105    }
106    return delegate instanceof Serializable
107        ? new MemoizingSupplier<T>(delegate)
108        : new NonSerializableMemoizingSupplier<T>(delegate);
109  }
110
111  @VisibleForTesting
112  static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
113    final Supplier<T> delegate;
114    transient volatile boolean initialized;
115    // "value" does not need to be volatile; visibility piggy-backs
116    // on volatile read of "initialized".
117    @NullableDecl transient T value;
118
119    MemoizingSupplier(Supplier<T> delegate) {
120      this.delegate = checkNotNull(delegate);
121    }
122
123    @Override
124    public T get() {
125      // A 2-field variant of Double Checked Locking.
126      if (!initialized) {
127        synchronized (this) {
128          if (!initialized) {
129            T t = delegate.get();
130            value = t;
131            initialized = true;
132            return t;
133          }
134        }
135      }
136      return value;
137    }
138
139    @Override
140    public String toString() {
141      return "Suppliers.memoize("
142          + (initialized ? "<supplier that returned " + value + ">" : delegate)
143          + ")";
144    }
145
146    private static final long serialVersionUID = 0;
147  }
148
149  @VisibleForTesting
150  static class NonSerializableMemoizingSupplier<T> implements Supplier<T> {
151    volatile Supplier<T> delegate;
152    volatile boolean initialized;
153    // "value" does not need to be volatile; visibility piggy-backs
154    // on volatile read of "initialized".
155    @NullableDecl T value;
156
157    NonSerializableMemoizingSupplier(Supplier<T> delegate) {
158      this.delegate = checkNotNull(delegate);
159    }
160
161    @Override
162    public T get() {
163      // A 2-field variant of Double Checked Locking.
164      if (!initialized) {
165        synchronized (this) {
166          if (!initialized) {
167            T t = delegate.get();
168            value = t;
169            initialized = true;
170            // Release the delegate to GC.
171            delegate = null;
172            return t;
173          }
174        }
175      }
176      return value;
177    }
178
179    @Override
180    public String toString() {
181      Supplier<T> delegate = this.delegate;
182      return "Suppliers.memoize("
183          + (delegate == null ? "<supplier that returned " + value + ">" : delegate)
184          + ")";
185    }
186  }
187
188  /**
189   * Returns a supplier that caches the instance supplied by the delegate and removes the cached
190   * value after the specified time has passed. Subsequent calls to {@code get()} return the cached
191   * value if the expiration time has not passed. After the expiration time, a new value is
192   * retrieved, cached, and returned. See: <a
193   * href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
194   *
195   * <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the
196   * cached value, which will be recalculated when {@code get()} is called on the reserialized
197   * instance. The actual memoization does not happen when the underlying delegate throws an
198   * exception.
199   *
200   * <p>When the underlying delegate throws an exception then this memoizing supplier will keep
201   * delegating calls until it returns valid data.
202   *
203   * @param duration the length of time after a value is created that it should stop being returned
204   *     by subsequent {@code get()} calls
205   * @param unit the unit that {@code duration} is expressed in
206   * @throws IllegalArgumentException if {@code duration} is not positive
207   * @since 2.0
208   */
209  @SuppressWarnings("GoodTime") // should accept a java.time.Duration
210  public static <T> Supplier<T> memoizeWithExpiration(
211      Supplier<T> delegate, long duration, TimeUnit unit) {
212    return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
213  }
214
215  @VisibleForTesting
216  @SuppressWarnings("GoodTime") // lots of violations
217  static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
218    final Supplier<T> delegate;
219    final long durationNanos;
220    @NullableDecl transient volatile T value;
221    // The special value 0 means "not yet initialized".
222    transient volatile long expirationNanos;
223
224    ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
225      this.delegate = checkNotNull(delegate);
226      this.durationNanos = unit.toNanos(duration);
227      checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit);
228    }
229
230    @Override
231    public T get() {
232      // Another variant of Double Checked Locking.
233      //
234      // We use two volatile reads. We could reduce this to one by
235      // putting our fields into a holder class, but (at least on x86)
236      // the extra memory consumption and indirection are more
237      // expensive than the extra volatile reads.
238      long nanos = expirationNanos;
239      long now = Platform.systemNanoTime();
240      if (nanos == 0 || now - nanos >= 0) {
241        synchronized (this) {
242          if (nanos == expirationNanos) { // recheck for lost race
243            T t = delegate.get();
244            value = t;
245            nanos = now + durationNanos;
246            // In the very unlikely event that nanos is 0, set it to 1;
247            // no one will notice 1 ns of tardiness.
248            expirationNanos = (nanos == 0) ? 1 : nanos;
249            return t;
250          }
251        }
252      }
253      return value;
254    }
255
256    @Override
257    public String toString() {
258      // This is a little strange if the unit the user provided was not NANOS,
259      // but we don't want to store the unit just for toString
260      return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
261    }
262
263    private static final long serialVersionUID = 0;
264  }
265
266  /** Returns a supplier that always supplies {@code instance}. */
267  public static <T> Supplier<T> ofInstance(@NullableDecl T instance) {
268    return new SupplierOfInstance<T>(instance);
269  }
270
271  private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
272    @NullableDecl final T instance;
273
274    SupplierOfInstance(@NullableDecl T instance) {
275      this.instance = instance;
276    }
277
278    @Override
279    public T get() {
280      return instance;
281    }
282
283    @Override
284    public boolean equals(@NullableDecl Object obj) {
285      if (obj instanceof SupplierOfInstance) {
286        SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
287        return Objects.equal(instance, that.instance);
288      }
289      return false;
290    }
291
292    @Override
293    public int hashCode() {
294      return Objects.hashCode(instance);
295    }
296
297    @Override
298    public String toString() {
299      return "Suppliers.ofInstance(" + instance + ")";
300    }
301
302    private static final long serialVersionUID = 0;
303  }
304
305  /**
306   * Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling
307   * it, making it thread-safe.
308   */
309  public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
310    return new ThreadSafeSupplier<T>(delegate);
311  }
312
313  private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
314    final Supplier<T> delegate;
315
316    ThreadSafeSupplier(Supplier<T> delegate) {
317      this.delegate = checkNotNull(delegate);
318    }
319
320    @Override
321    public T get() {
322      synchronized (delegate) {
323        return delegate.get();
324      }
325    }
326
327    @Override
328    public String toString() {
329      return "Suppliers.synchronizedSupplier(" + delegate + ")";
330    }
331
332    private static final long serialVersionUID = 0;
333  }
334
335  /**
336   * Returns a function that accepts a supplier and returns the result of invoking {@link
337   * Supplier#get} on that supplier.
338   *
339   * <p><b>Java 8 users:</b> use the method reference {@code Supplier::get} instead.
340   *
341   * @since 8.0
342   */
343  public static <T> Function<Supplier<T>, T> supplierFunction() {
344    @SuppressWarnings("unchecked") // implementation is "fully variant"
345    SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
346    return sf;
347  }
348
349  private interface SupplierFunction<T> extends Function<Supplier<T>, T> {}
350
351  private enum SupplierFunctionImpl implements SupplierFunction<Object> {
352    INSTANCE;
353
354    // Note: This makes T a "pass-through type"
355    @Override
356    public Object apply(Supplier<Object> input) {
357      return input.get();
358    }
359
360    @Override
361    public String toString() {
362      return "Suppliers.supplierFunction()";
363    }
364  }
365}