1/*
2 * Copyright (C) 2007 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.base;
18
19import com.google.common.annotations.Beta;
20import com.google.common.annotations.GwtCompatible;
21import com.google.common.annotations.VisibleForTesting;
22
23import java.io.Serializable;
24import java.util.concurrent.TimeUnit;
25
26import javax.annotation.Nullable;
27
28/**
29 * Useful suppliers.
30 *
31 * <p>All methods return serializable suppliers as long as they're given
32 * serializable parameters.
33 *
34 * @author Laurence Gonsalves
35 * @author Harry Heymann
36 * @since 2.0 (imported from Google Collections Library)
37 */
38@GwtCompatible
39public final class Suppliers {
40  private Suppliers() {}
41
42  /**
43   * Returns a new supplier which is the composition of the provided function
44   * and supplier. In other words, the new supplier's value will be computed by
45   * retrieving the value from {@code supplier}, and then applying
46   * {@code function} to that value. Note that the resulting supplier will not
47   * call {@code supplier} or invoke {@code function} until it is called.
48   */
49  public static <F, T> Supplier<T> compose(
50      Function<? super F, T> function, Supplier<F> supplier) {
51    Preconditions.checkNotNull(function);
52    Preconditions.checkNotNull(supplier);
53    return new SupplierComposition<F, T>(function, supplier);
54  }
55
56  private static class SupplierComposition<F, T>
57      implements Supplier<T>, Serializable {
58    final Function<? super F, T> function;
59    final Supplier<F> supplier;
60
61    SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
62      this.function = function;
63      this.supplier = supplier;
64    }
65    @Override
66    public T get() {
67      return function.apply(supplier.get());
68    }
69    private static final long serialVersionUID = 0;
70  }
71
72  /**
73   * Returns a supplier which caches the instance retrieved during the first
74   * call to {@code get()} and returns that value on subsequent calls to
75   * {@code get()}. See:
76   * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
77   *
78   * <p>The returned supplier is thread-safe. The supplier's serialized form
79   * does not contain the cached value, which will be recalculated when {@code
80   * get()} is called on the reserialized instance.
81   *
82   * <p>If {@code delegate} is an instance created by an earlier call to {@code
83   * memoize}, it is returned directly.
84   */
85  public static <T> Supplier<T> memoize(Supplier<T> delegate) {
86    return (delegate instanceof MemoizingSupplier)
87        ? delegate
88        : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
89  }
90
91  @VisibleForTesting
92  static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
93    final Supplier<T> delegate;
94    transient volatile boolean initialized;
95    // "value" does not need to be volatile; visibility piggy-backs
96    // on volatile read of "initialized".
97    transient T value;
98
99    MemoizingSupplier(Supplier<T> delegate) {
100      this.delegate = delegate;
101    }
102
103    @Override
104    public T get() {
105      // A 2-field variant of Double Checked Locking.
106      if (!initialized) {
107        synchronized (this) {
108          if (!initialized) {
109            T t = delegate.get();
110            value = t;
111            initialized = true;
112            return t;
113          }
114        }
115      }
116      return value;
117    }
118
119    private static final long serialVersionUID = 0;
120  }
121
122  /**
123   * Returns a supplier that caches the instance supplied by the delegate and
124   * removes the cached value after the specified time has passed. Subsequent
125   * calls to {@code get()} return the cached value if the expiration time has
126   * not passed. After the expiration time, a new value is retrieved, cached,
127   * and returned. See:
128   * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
129   *
130   * <p>The returned supplier is thread-safe. The supplier's serialized form
131   * does not contain the cached value, which will be recalculated when {@code
132   * get()} is called on the reserialized instance.
133   *
134   * @param duration the length of time after a value is created that it
135   *     should stop being returned by subsequent {@code get()} calls
136   * @param unit the unit that {@code duration} is expressed in
137   * @throws IllegalArgumentException if {@code duration} is not positive
138   * @since 2.0
139   */
140  public static <T> Supplier<T> memoizeWithExpiration(
141      Supplier<T> delegate, long duration, TimeUnit unit) {
142    return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
143  }
144
145  @VisibleForTesting static class ExpiringMemoizingSupplier<T>
146      implements Supplier<T>, Serializable {
147    final Supplier<T> delegate;
148    final long durationNanos;
149    transient volatile T value;
150    // The special value 0 means "not yet initialized".
151    transient volatile long expirationNanos;
152
153    ExpiringMemoizingSupplier(
154        Supplier<T> delegate, long duration, TimeUnit unit) {
155      this.delegate = Preconditions.checkNotNull(delegate);
156      this.durationNanos = unit.toNanos(duration);
157      Preconditions.checkArgument(duration > 0);
158    }
159
160    @Override
161    public T get() {
162      // Another variant of Double Checked Locking.
163      //
164      // We use two volatile reads.  We could reduce this to one by
165      // putting our fields into a holder class, but (at least on x86)
166      // the extra memory consumption and indirection are more
167      // expensive than the extra volatile reads.
168      long nanos = expirationNanos;
169      long now = Platform.systemNanoTime();
170      if (nanos == 0 || now - nanos >= 0) {
171        synchronized (this) {
172          if (nanos == expirationNanos) {  // recheck for lost race
173            T t = delegate.get();
174            value = t;
175            nanos = now + durationNanos;
176            // In the very unlikely event that nanos is 0, set it to 1;
177            // no one will notice 1 ns of tardiness.
178            expirationNanos = (nanos == 0) ? 1 : nanos;
179            return t;
180          }
181        }
182      }
183      return value;
184    }
185
186    private static final long serialVersionUID = 0;
187  }
188
189  /**
190   * Returns a supplier that always supplies {@code instance}.
191   */
192  public static <T> Supplier<T> ofInstance(@Nullable T instance) {
193    return new SupplierOfInstance<T>(instance);
194  }
195
196  private static class SupplierOfInstance<T>
197      implements Supplier<T>, Serializable {
198    final T instance;
199
200    SupplierOfInstance(@Nullable T instance) {
201      this.instance = instance;
202    }
203    @Override
204    public T get() {
205      return instance;
206    }
207    private static final long serialVersionUID = 0;
208  }
209
210  /**
211   * Returns a supplier whose {@code get()} method synchronizes on
212   * {@code delegate} before calling it, making it thread-safe.
213   */
214  public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
215    return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
216  }
217
218  private static class ThreadSafeSupplier<T>
219      implements Supplier<T>, Serializable {
220    final Supplier<T> delegate;
221
222    ThreadSafeSupplier(Supplier<T> delegate) {
223      this.delegate = delegate;
224    }
225    @Override
226    public T get() {
227      synchronized (delegate) {
228        return delegate.get();
229      }
230    }
231    private static final long serialVersionUID = 0;
232  }
233
234  /**
235   * Returns a function that accepts a supplier and returns the result of
236   * invoking {@link Supplier#get} on that supplier.
237   *
238   * @since 8.0
239   */
240  @Beta
241  @SuppressWarnings("unchecked") // SupplierFunction works for any T.
242  public static <T> Function<Supplier<T>, T> supplierFunction() {
243    return (Function) SupplierFunction.INSTANCE;
244  }
245
246  private enum SupplierFunction implements Function<Supplier<?>, Object> {
247    INSTANCE;
248
249    @Override
250    public Object apply(Supplier<?> input) {
251      return input.get();
252    }
253  }
254}
255