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