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.Nullable;
027
028/**
029 * Useful suppliers.
030 *
031 * <p>All methods return serializable suppliers as long as they're given
032 * serializable parameters.
033 *
034 * @author Laurence Gonsalves
035 * @author Harry Heymann
036 * @since 2.0 (imported from Google Collections Library)
037 */
038@GwtCompatible
039public final class Suppliers {
040  private Suppliers() {}
041
042  /**
043   * Returns a new supplier which is the composition of the provided function
044   * and supplier. In other words, the new supplier's value will be computed by
045   * retrieving the value from {@code supplier}, and then applying
046   * {@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, T> Supplier<T> compose(
050      Function<? super F, T> function, Supplier<F> supplier) {
051    Preconditions.checkNotNull(function);
052    Preconditions.checkNotNull(supplier);
053    return new SupplierComposition<F, T>(function, supplier);
054  }
055
056  private static class SupplierComposition<F, T>
057      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 String toString() {
073      return "Suppliers.compose(" + function + ", " + supplier + ")";
074    }
075
076    private static final long serialVersionUID = 0;
077  }
078
079  /**
080   * Returns a supplier which caches the instance retrieved during the first
081   * call to {@code get()} and returns that value on subsequent calls to
082   * {@code get()}. See:
083   * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
084   *
085   * <p>The returned supplier is thread-safe. The supplier's serialized form
086   * does not contain the cached value, which will be recalculated when {@code
087   * get()} is called on the reserialized instance.
088   *
089   * <p>If {@code delegate} is an instance created by an earlier call to {@code
090   * memoize}, it is returned directly.
091   */
092  public static <T> Supplier<T> memoize(Supplier<T> delegate) {
093    return (delegate instanceof MemoizingSupplier)
094        ? delegate
095        : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
096  }
097
098  @VisibleForTesting
099  static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
100    final Supplier<T> delegate;
101    transient volatile boolean initialized;
102    // "value" does not need to be volatile; visibility piggy-backs
103    // on volatile read of "initialized".
104    transient T value;
105
106    MemoizingSupplier(Supplier<T> delegate) {
107      this.delegate = delegate;
108    }
109
110    @Override
111    public T get() {
112      // A 2-field variant of Double Checked Locking.
113      if (!initialized) {
114        synchronized (this) {
115          if (!initialized) {
116            T t = delegate.get();
117            value = t;
118            initialized = true;
119            return t;
120          }
121        }
122      }
123      return value;
124    }
125
126    @Override
127    public String toString() {
128      return "Suppliers.memoize(" + delegate + ")";
129    }
130
131    private static final long serialVersionUID = 0;
132  }
133
134  /**
135   * Returns a supplier that caches the instance supplied by the delegate and
136   * removes the cached value after the specified time has passed. Subsequent
137   * calls to {@code get()} return the cached value if the expiration time has
138   * not passed. After the expiration time, a new value is retrieved, cached,
139   * and returned. See:
140   * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
141   *
142   * <p>The returned supplier is thread-safe. The supplier's serialized form
143   * does not contain the cached value, which will be recalculated when {@code
144   * get()} is called on the reserialized instance.
145   *
146   * @param duration the length of time after a value is created that it
147   *     should stop being returned by subsequent {@code get()} calls
148   * @param unit the unit that {@code duration} is expressed in
149   * @throws IllegalArgumentException if {@code duration} is not positive
150   * @since 2.0
151   */
152  public static <T> Supplier<T> memoizeWithExpiration(
153      Supplier<T> delegate, long duration, TimeUnit unit) {
154    return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
155  }
156
157  @VisibleForTesting static class ExpiringMemoizingSupplier<T>
158      implements Supplier<T>, Serializable {
159    final Supplier<T> delegate;
160    final long durationNanos;
161    transient volatile T value;
162    // The special value 0 means "not yet initialized".
163    transient volatile long expirationNanos;
164
165    ExpiringMemoizingSupplier(
166        Supplier<T> delegate, long duration, TimeUnit unit) {
167      this.delegate = Preconditions.checkNotNull(delegate);
168      this.durationNanos = unit.toNanos(duration);
169      Preconditions.checkArgument(duration > 0);
170    }
171
172    @Override
173    public T get() {
174      // Another variant of Double Checked Locking.
175      //
176      // We use two volatile reads.  We could reduce this to one by
177      // putting our fields into a holder class, but (at least on x86)
178      // the extra memory consumption and indirection are more
179      // expensive than the extra volatile reads.
180      long nanos = expirationNanos;
181      long now = Platform.systemNanoTime();
182      if (nanos == 0 || now - nanos >= 0) {
183        synchronized (this) {
184          if (nanos == expirationNanos) {  // recheck for lost race
185            T t = delegate.get();
186            value = t;
187            nanos = now + durationNanos;
188            // In the very unlikely event that nanos is 0, set it to 1;
189            // no one will notice 1 ns of tardiness.
190            expirationNanos = (nanos == 0) ? 1 : nanos;
191            return t;
192          }
193        }
194      }
195      return value;
196    }
197
198    @Override
199    public String toString() {
200      // This is a little strange if the unit the user provided was not NANOS,
201      // but we don't want to store the unit just for toString
202      return "Suppliers.memoizeWithExpiration(" + delegate + ", " +
203          durationNanos + ", NANOS)";
204    }
205
206    private static final long serialVersionUID = 0;
207  }
208
209  /**
210   * Returns a supplier that always supplies {@code instance}.
211   */
212  public static <T> Supplier<T> ofInstance(@Nullable T instance) {
213    return new SupplierOfInstance<T>(instance);
214  }
215
216  private static class SupplierOfInstance<T>
217      implements Supplier<T>, Serializable {
218    final T instance;
219
220    SupplierOfInstance(@Nullable T instance) {
221      this.instance = instance;
222    }
223
224    @Override
225    public T get() {
226      return instance;
227    }
228
229    @Override
230    public String toString() {
231      return "Suppliers.ofInstance(" + instance + ")";
232    }
233
234    private static final long serialVersionUID = 0;
235  }
236
237  /**
238   * Returns a supplier whose {@code get()} method synchronizes on
239   * {@code delegate} before calling it, making it thread-safe.
240   */
241  public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
242    return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
243  }
244
245  private static class ThreadSafeSupplier<T>
246      implements Supplier<T>, Serializable {
247    final Supplier<T> delegate;
248
249    ThreadSafeSupplier(Supplier<T> delegate) {
250      this.delegate = delegate;
251    }
252
253    @Override
254    public T get() {
255      synchronized (delegate) {
256        return delegate.get();
257      }
258    }
259
260    @Override
261    public String toString() {
262      return "Suppliers.synchronizedSupplier(" + delegate + ")";
263    }
264
265    private static final long serialVersionUID = 0;
266  }
267
268  /**
269   * Returns a function that accepts a supplier and returns the result of
270   * invoking {@link Supplier#get} on that supplier.
271   *
272   * @since 8.0
273   */
274  @Beta
275  @SuppressWarnings("unchecked") // SupplierFunction works for any T.
276  public static <T> Function<Supplier<T>, T> supplierFunction() {
277    return (Function) SupplierFunction.INSTANCE;
278  }
279
280  private enum SupplierFunction implements Function<Supplier<?>, Object> {
281    INSTANCE;
282
283    @Override
284    public Object apply(Supplier<?> input) {
285      return input.get();
286    }
287
288    @Override
289    public String toString() {
290      return "Suppliers.supplierFunction()";
291    }
292  }
293}