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