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