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