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  public static <T> Supplier<T> memoizeWithExpiration(
210      Supplier<T> delegate, long duration, TimeUnit unit) {
211    return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
212  }
213
214  @VisibleForTesting
215  static class ExpiringMemoizingSupplier<T> implements Supplier<T>, Serializable {
216    final Supplier<T> delegate;
217    final long durationNanos;
218    transient volatile @Nullable T value;
219    // The special value 0 means "not yet initialized".
220    transient volatile long expirationNanos;
221
222    ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) {
223      this.delegate = checkNotNull(delegate);
224      this.durationNanos = unit.toNanos(duration);
225      checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit);
226    }
227
228    @Override
229    public T get() {
230      // Another variant of Double Checked Locking.
231      //
232      // We use two volatile reads. We could reduce this to one by
233      // putting our fields into a holder class, but (at least on x86)
234      // the extra memory consumption and indirection are more
235      // expensive than the extra volatile reads.
236      long nanos = expirationNanos;
237      long now = Platform.systemNanoTime();
238      if (nanos == 0 || now - nanos >= 0) {
239        synchronized (this) {
240          if (nanos == expirationNanos) { // recheck for lost race
241            T t = delegate.get();
242            value = t;
243            nanos = now + durationNanos;
244            // In the very unlikely event that nanos is 0, set it to 1;
245            // no one will notice 1 ns of tardiness.
246            expirationNanos = (nanos == 0) ? 1 : nanos;
247            return t;
248          }
249        }
250      }
251      return value;
252    }
253
254    @Override
255    public String toString() {
256      // This is a little strange if the unit the user provided was not NANOS,
257      // but we don't want to store the unit just for toString
258      return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)";
259    }
260
261    private static final long serialVersionUID = 0;
262  }
263
264  /** Returns a supplier that always supplies {@code instance}. */
265  public static <T> Supplier<T> ofInstance(@Nullable T instance) {
266    return new SupplierOfInstance<T>(instance);
267  }
268
269  private static class SupplierOfInstance<T> implements Supplier<T>, Serializable {
270    final @Nullable T instance;
271
272    SupplierOfInstance(@Nullable T instance) {
273      this.instance = instance;
274    }
275
276    @Override
277    public T get() {
278      return instance;
279    }
280
281    @Override
282    public boolean equals(@Nullable Object obj) {
283      if (obj instanceof SupplierOfInstance) {
284        SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj;
285        return Objects.equal(instance, that.instance);
286      }
287      return false;
288    }
289
290    @Override
291    public int hashCode() {
292      return Objects.hashCode(instance);
293    }
294
295    @Override
296    public String toString() {
297      return "Suppliers.ofInstance(" + instance + ")";
298    }
299
300    private static final long serialVersionUID = 0;
301  }
302
303  /**
304   * Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling
305   * it, making it thread-safe.
306   */
307  public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
308    return new ThreadSafeSupplier<T>(delegate);
309  }
310
311  private static class ThreadSafeSupplier<T> implements Supplier<T>, Serializable {
312    final Supplier<T> delegate;
313
314    ThreadSafeSupplier(Supplier<T> delegate) {
315      this.delegate = checkNotNull(delegate);
316    }
317
318    @Override
319    public T get() {
320      synchronized (delegate) {
321        return delegate.get();
322      }
323    }
324
325    @Override
326    public String toString() {
327      return "Suppliers.synchronizedSupplier(" + delegate + ")";
328    }
329
330    private static final long serialVersionUID = 0;
331  }
332
333  /**
334   * Returns a function that accepts a supplier and returns the result of invoking {@link
335   * Supplier#get} on that supplier.
336   *
337   * <p><b>Java 8 users:</b> use the method reference {@code Supplier::get} instead.
338   *
339   * @since 8.0
340   */
341  public static <T> Function<Supplier<T>, T> supplierFunction() {
342    @SuppressWarnings("unchecked") // implementation is "fully variant"
343    SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE;
344    return sf;
345  }
346
347  private interface SupplierFunction<T> extends Function<Supplier<T>, T> {}
348
349  private enum SupplierFunctionImpl implements SupplierFunction<Object> {
350    INSTANCE;
351
352    // Note: This makes T a "pass-through type"
353    @Override
354    public Object apply(Supplier<Object> input) {
355      return input.get();
356    }
357
358    @Override
359    public String toString() {
360      return "Suppliers.supplierFunction()";
361    }
362  }
363}