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.Internal.toNanosSaturated;
018import static com.google.common.base.NullnessCasts.uncheckedCastNullableTToT;
019import static com.google.common.base.Preconditions.checkArgument;
020import static com.google.common.base.Preconditions.checkNotNull;
021
022import com.google.common.annotations.GwtCompatible;
023import com.google.common.annotations.GwtIncompatible;
024import com.google.common.annotations.J2ktIncompatible;
025import com.google.common.annotations.VisibleForTesting;
026import java.io.Serializable;
027import java.time.Duration;
028import java.util.concurrent.TimeUnit;
029import javax.annotation.CheckForNull;
030import org.checkerframework.checker.nullness.qual.Nullable;
031
032/**
033 * Useful suppliers.
034 *
035 * <p>All methods return serializable suppliers as long as they're given serializable parameters.
036 *
037 * @author Laurence Gonsalves
038 * @author Harry Heymann
039 * @since 2.0
040 */
041@GwtCompatible(emulated = true)
042@ElementTypesAreNonnullByDefault
043public final class Suppliers {
044  private Suppliers() {}
045
046  /**
047   * Returns a new supplier which is the composition of the provided function and supplier. In other
048   * words, the new supplier's value will be computed by retrieving the value from {@code supplier},
049   * and then applying {@code function} to that value. Note that the resulting supplier will not
050   * call {@code supplier} or invoke {@code function} until it is called.
051   */
052  public static <F extends @Nullable Object, T extends @Nullable Object> Supplier<T> compose(
053      Function<? super F, T> function, Supplier<F> supplier) {
054    return new SupplierComposition<>(function, supplier);
055  }
056
057  private static class SupplierComposition<F extends @Nullable Object, T extends @Nullable Object>
058      implements Supplier<T>, Serializable {
059    final Function<? super F, T> function;
060    final Supplier<F> supplier;
061
062    SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
063      this.function = checkNotNull(function);
064      this.supplier = checkNotNull(supplier);
065    }
066
067    @Override
068    @ParametricNullness
069    public T get() {
070      return function.apply(supplier.get());
071    }
072
073    @Override
074    public boolean equals(@CheckForNull Object obj) {
075      if (obj instanceof SupplierComposition) {
076        SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj;
077        return function.equals(that.function) && supplier.equals(that.supplier);
078      }
079      return false;
080    }
081
082    @Override
083    public int hashCode() {
084      return Objects.hashCode(function, supplier);
085    }
086
087    @Override
088    public String toString() {
089      return "Suppliers.compose(" + function + ", " + supplier + ")";
090    }
091
092    private static final long serialVersionUID = 0;
093  }
094
095  /**
096   * Returns a supplier which caches the instance retrieved during the first call to {@code get()}
097   * and returns that value on subsequent calls to {@code get()}. See: <a
098   * href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
099   *
100   * <p>The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at
101   * most once unless the underlying {@code get()} throws an exception. The supplier's serialized
102   * form does not contain the cached value, which will be recalculated when {@code get()} is called
103   * on the deserialized instance.
104   *
105   * <p>When the underlying delegate throws an exception then this memoizing supplier will keep
106   * delegating calls until it returns valid data.
107   *
108   * <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is
109   * returned directly.
110   */
111  public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) {
112    if (delegate instanceof NonSerializableMemoizingSupplier
113        || delegate instanceof MemoizingSupplier) {
114      return delegate;
115    }
116    return delegate instanceof Serializable
117        ? new MemoizingSupplier<T>(delegate)
118        : new NonSerializableMemoizingSupplier<T>(delegate);
119  }
120
121  @VisibleForTesting
122  static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T>, Serializable {
123    private final Object lock =
124        new Integer(1); // something serializable
125
126    final Supplier<T> delegate;
127    transient volatile boolean initialized;
128    // "value" does not need to be volatile; visibility piggy-backs
129    // on volatile read of "initialized".
130    @CheckForNull transient T value;
131
132    MemoizingSupplier(Supplier<T> delegate) {
133      this.delegate = checkNotNull(delegate);
134    }
135
136    @Override
137    @ParametricNullness
138    public T get() {
139      // A 2-field variant of Double Checked Locking.
140      if (!initialized) {
141        synchronized (lock) {
142          if (!initialized) {
143            T t = delegate.get();
144            value = t;
145            initialized = true;
146            return t;
147          }
148        }
149      }
150      // This is safe because we checked `initialized`.
151      return uncheckedCastNullableTToT(value);
152    }
153
154    @Override
155    public String toString() {
156      return "Suppliers.memoize("
157          + (initialized ? "<supplier that returned " + value + ">" : delegate)
158          + ")";
159    }
160
161    private static final long serialVersionUID = 0;
162  }
163
164  @VisibleForTesting
165  static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> {
166    private final Object lock = new Object();
167
168    @SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object
169    private static final Supplier<Void> SUCCESSFULLY_COMPUTED =
170        () -> {
171          throw new IllegalStateException(); // Should never get called.
172        };
173
174    private volatile Supplier<T> delegate;
175    // "value" does not need to be volatile; visibility piggy-backs on volatile read of "delegate".
176    @CheckForNull private T value;
177
178    NonSerializableMemoizingSupplier(Supplier<T> delegate) {
179      this.delegate = checkNotNull(delegate);
180    }
181
182    @Override
183    @ParametricNullness
184    @SuppressWarnings("unchecked") // Cast from Supplier<Void> to Supplier<T> is always valid
185    public T get() {
186      // Because Supplier is read-heavy, we use the "double-checked locking" pattern.
187      if (delegate != SUCCESSFULLY_COMPUTED) {
188        synchronized (lock) {
189          if (delegate != SUCCESSFULLY_COMPUTED) {
190            T t = delegate.get();
191            value = t;
192            delegate = (Supplier<T>) SUCCESSFULLY_COMPUTED;
193            return t;
194          }
195        }
196      }
197      // This is safe because we checked `delegate`.
198      return uncheckedCastNullableTToT(value);
199    }
200
201    @Override
202    public String toString() {
203      Supplier<T> delegate = this.delegate;
204      return "Suppliers.memoize("
205          + (delegate == SUCCESSFULLY_COMPUTED
206              ? "<supplier that returned " + value + ">"
207              : delegate)
208          + ")";
209    }
210  }
211
212  /**
213   * Returns a supplier that caches the instance supplied by the delegate and removes the cached
214   * value after the specified time has passed. Subsequent calls to {@code get()} return the cached
215   * value if the expiration time has not passed. After the expiration time, a new value is
216   * retrieved, cached, and returned. See: <a
217   * href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
218   *
219   * <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the
220   * cached value, which will be recalculated when {@code get()} is called on the reserialized
221   * instance. The actual memoization does not happen when the underlying delegate throws an
222   * exception.
223   *
224   * <p>When the underlying delegate throws an exception then this memoizing supplier will keep
225   * delegating calls until it returns valid data.
226   *
227   * @param duration the length of time after a value is created that it should stop being returned
228   *     by subsequent {@code get()} calls
229   * @param unit the unit that {@code duration} is expressed in
230   * @throws IllegalArgumentException if {@code duration} is not positive
231   * @since 2.0
232   */
233  @SuppressWarnings("GoodTime") // Prefer the Duration overload
234  public static <T extends @Nullable Object> Supplier<T> memoizeWithExpiration(
235      Supplier<T> delegate, long duration, TimeUnit unit) {
236    checkNotNull(delegate);
237    checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit);
238    return new ExpiringMemoizingSupplier<>(delegate, unit.toNanos(duration));
239  }
240
241  /**
242   * Returns a supplier that caches the instance supplied by the delegate and removes the cached
243   * value after the specified time has passed. Subsequent calls to {@code get()} return the cached
244   * value if the expiration time has not passed. After the expiration time, a new value is
245   * retrieved, cached, and returned. See: <a
246   * href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
247   *
248   * <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the
249   * cached value, which will be recalculated when {@code get()} is called on the reserialized
250   * instance. The actual memoization does not happen when the underlying delegate throws an
251   * exception.
252   *
253   * <p>When the underlying delegate throws an exception then this memoizing supplier will keep
254   * delegating calls until it returns valid data.
255   *
256   * @param duration the length of time after a value is created that it should stop being returned
257   *     by subsequent {@code get()} calls
258   * @throws IllegalArgumentException if {@code duration} is not positive
259   * @since 33.1.0
260   */
261  @J2ktIncompatible
262  @GwtIncompatible // java.time.Duration
263  @SuppressWarnings("Java7ApiChecker") // no more dangerous that wherever the user got the Duration
264  @IgnoreJRERequirement
265  public static <T extends @Nullable Object> Supplier<T> memoizeWithExpiration(
266      Supplier<T> delegate, Duration duration) {
267    checkNotNull(delegate);
268    // The alternative of `duration.compareTo(Duration.ZERO) > 0` causes J2ObjC trouble.
269    checkArgument(
270        !duration.isNegative() && !duration.isZero(), "duration (%s) must be > 0", duration);
271    return new ExpiringMemoizingSupplier<>(delegate, toNanosSaturated(duration));
272  }
273
274  @VisibleForTesting
275  @SuppressWarnings("GoodTime") // lots of violations
276  static class ExpiringMemoizingSupplier<T extends @Nullable Object>
277      implements Supplier<T>, Serializable {
278    private final Object lock =
279        new Integer(1); // something serializable
280
281    final Supplier<T> delegate;
282    final long durationNanos;
283    @CheckForNull transient volatile T value;
284    // The special value 0 means "not yet initialized".
285    transient volatile long expirationNanos;
286
287    ExpiringMemoizingSupplier(Supplier<T> delegate, long durationNanos) {
288      this.delegate = delegate;
289      this.durationNanos = durationNanos;
290    }
291
292    @Override
293    @ParametricNullness
294    public T get() {
295      // Another variant of Double Checked Locking.
296      //
297      // We use two volatile reads. We could reduce this to one by
298      // putting our fields into a holder class, but (at least on x86)
299      // the extra memory consumption and indirection are more
300      // expensive than the extra volatile reads.
301      long nanos = expirationNanos;
302      long now = System.nanoTime();
303      if (nanos == 0 || now - nanos >= 0) {
304        synchronized (lock) {
305          if (nanos == expirationNanos) { // recheck for lost race
306            T t = delegate.get();
307            value = t;
308            nanos = now + durationNanos;
309            // In the very unlikely event that nanos is 0, set it to 1;
310            // no one will notice 1 ns of tardiness.
311            expirationNanos = (nanos == 0) ? 1 : nanos;
312            return t;
313          }
314        }
315      }
316      // This is safe because we checked `expirationNanos`.
317      return uncheckedCastNullableTToT(value);
318    }
319
320    @Override
321    public String toString() {
322      // This is a little strange if the unit the user provided was not NANOS,
323      // but we don't want to store the unit just for toString
324      return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
325    }
326
327    private static final long serialVersionUID = 0;
328  }
329
330  /** Returns a supplier that always supplies {@code instance}. */
331  public static <T extends @Nullable Object> Supplier<T> ofInstance(
332      @ParametricNullness T instance) {
333    return new SupplierOfInstance<>(instance);
334  }
335
336  private static class SupplierOfInstance<T extends @Nullable Object>
337      implements Supplier<T>, Serializable {
338    @ParametricNullness final T instance;
339
340    SupplierOfInstance(@ParametricNullness T instance) {
341      this.instance = instance;
342    }
343
344    @Override
345    @ParametricNullness
346    public T get() {
347      return instance;
348    }
349
350    @Override
351    public boolean equals(@CheckForNull Object obj) {
352      if (obj instanceof SupplierOfInstance) {
353        SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
354        return Objects.equal(instance, that.instance);
355      }
356      return false;
357    }
358
359    @Override
360    public int hashCode() {
361      return Objects.hashCode(instance);
362    }
363
364    @Override
365    public String toString() {
366      return "Suppliers.ofInstance(" + instance + ")";
367    }
368
369    private static final long serialVersionUID = 0;
370  }
371
372  /**
373   * Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling
374   * it, making it thread-safe.
375   */
376  @J2ktIncompatible
377  public static <T extends @Nullable Object> Supplier<T> synchronizedSupplier(
378      Supplier<T> delegate) {
379    return new ThreadSafeSupplier<>(delegate);
380  }
381
382  @J2ktIncompatible
383  private static class ThreadSafeSupplier<T extends @Nullable Object>
384      implements Supplier<T>, Serializable {
385    final Supplier<T> delegate;
386
387    ThreadSafeSupplier(Supplier<T> delegate) {
388      this.delegate = checkNotNull(delegate);
389    }
390
391    @Override
392    @ParametricNullness
393    public T get() {
394      synchronized (delegate) {
395        return delegate.get();
396      }
397    }
398
399    @Override
400    public String toString() {
401      return "Suppliers.synchronizedSupplier(" + delegate + ")";
402    }
403
404    private static final long serialVersionUID = 0;
405  }
406
407  /**
408   * Returns a function that accepts a supplier and returns the result of invoking {@link
409   * Supplier#get} on that supplier.
410   *
411   * <p><b>Java 8+ users:</b> use the method reference {@code Supplier::get} instead.
412   *
413   * @since 8.0
414   */
415  public static <T extends @Nullable Object> Function<Supplier<T>, T> supplierFunction() {
416    @SuppressWarnings("unchecked") // implementation is "fully variant"
417    SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
418    return sf;
419  }
420
421  private interface SupplierFunction<T extends @Nullable Object> extends Function<Supplier<T>, T> {}
422
423  private enum SupplierFunctionImpl implements SupplierFunction<@Nullable Object> {
424    INSTANCE;
425
426    // Note: This makes T a "pass-through type"
427    @Override
428    @CheckForNull
429    public Object apply(Supplier<@Nullable Object> input) {
430      return input.get();
431    }
432
433    @Override
434    public String toString() {
435      return "Suppliers.supplierFunction()";
436    }
437  }
438}