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