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