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 (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    @Override
066    public T get() {
067      return function.apply(supplier.get());
068    }
069    private static final long serialVersionUID = 0;
070  }
071
072  /**
073   * Returns a supplier which caches the instance retrieved during the first
074   * call to {@code get()} and returns that value on subsequent calls to
075   * {@code get()}. See:
076   * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
077   *
078   * <p>The returned supplier is thread-safe. The supplier's serialized form
079   * does not contain the cached value, which will be recalculated when {@code
080   * get()} is called on the reserialized instance.
081   *
082   * <p>If {@code delegate} is an instance created by an earlier call to {@code
083   * memoize}, it is returned directly.
084   */
085  public static <T> Supplier<T> memoize(Supplier<T> delegate) {
086    return (delegate instanceof MemoizingSupplier)
087        ? delegate
088        : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
089  }
090
091  @VisibleForTesting
092  static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
093    final Supplier<T> delegate;
094    transient volatile boolean initialized;
095    // "value" does not need to be volatile; visibility piggy-backs
096    // on volatile read of "initialized".
097    transient T value;
098
099    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
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
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}