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    
017    package com.google.common.base;
018    
019    import com.google.common.annotations.Beta;
020    import com.google.common.annotations.GwtCompatible;
021    import com.google.common.annotations.VisibleForTesting;
022    
023    import java.io.Serializable;
024    import java.util.concurrent.TimeUnit;
025    
026    import 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
039    public 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    }