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