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