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        
067        public T get() {
068          return function.apply(supplier.get());
069        }
070    
071        
072        @Override
073        public String toString() {
074          return "Suppliers.compose(" + function + ", " + supplier + ")";
075        }
076    
077        private static final long serialVersionUID = 0;
078      }
079    
080      /**
081       * Returns a supplier which caches the instance retrieved during the first
082       * call to {@code get()} and returns that value on subsequent calls to
083       * {@code get()}. See:
084       * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
085       *
086       * <p>The returned supplier is thread-safe. The supplier's serialized form
087       * does not contain the cached value, which will be recalculated when {@code
088       * get()} is called on the reserialized instance.
089       *
090       * <p>If {@code delegate} is an instance created by an earlier call to {@code
091       * memoize}, it is returned directly.
092       */
093      public static <T> Supplier<T> memoize(Supplier<T> delegate) {
094        return (delegate instanceof MemoizingSupplier)
095            ? delegate
096            : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
097      }
098    
099      @VisibleForTesting
100      static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
101        final Supplier<T> delegate;
102        transient volatile boolean initialized;
103        // "value" does not need to be volatile; visibility piggy-backs
104        // on volatile read of "initialized".
105        transient T value;
106    
107        MemoizingSupplier(Supplier<T> delegate) {
108          this.delegate = delegate;
109        }
110    
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        
127        @Override
128        public String toString() {
129          return "Suppliers.memoize(" + delegate + ")";
130        }
131    
132        private static final long serialVersionUID = 0;
133      }
134    
135      /**
136       * Returns a supplier that caches the instance supplied by the delegate and
137       * removes the cached value after the specified time has passed. Subsequent
138       * calls to {@code get()} return the cached value if the expiration time has
139       * not passed. After the expiration time, a new value is retrieved, cached,
140       * and returned. See:
141       * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
142       *
143       * <p>The returned supplier is thread-safe. The supplier's serialized form
144       * does not contain the cached value, which will be recalculated when {@code
145       * get()} is called on the reserialized instance.
146       *
147       * @param duration the length of time after a value is created that it
148       *     should stop being returned by subsequent {@code get()} calls
149       * @param unit the unit that {@code duration} is expressed in
150       * @throws IllegalArgumentException if {@code duration} is not positive
151       * @since 2.0
152       */
153      public static <T> Supplier<T> memoizeWithExpiration(
154          Supplier<T> delegate, long duration, TimeUnit unit) {
155        return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
156      }
157    
158      @VisibleForTesting static class ExpiringMemoizingSupplier<T>
159          implements Supplier<T>, Serializable {
160        final Supplier<T> delegate;
161        final long durationNanos;
162        transient volatile T value;
163        // The special value 0 means "not yet initialized".
164        transient volatile long expirationNanos;
165    
166        ExpiringMemoizingSupplier(
167            Supplier<T> delegate, long duration, TimeUnit unit) {
168          this.delegate = Preconditions.checkNotNull(delegate);
169          this.durationNanos = unit.toNanos(duration);
170          Preconditions.checkArgument(duration > 0);
171        }
172    
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        
199        @Override
200        public String toString() {
201          // This is a little strange if the unit the user provided was not NANOS,
202          // but we don't want to store the unit just for toString
203          return "Suppliers.memoizeWithExpiration(" + delegate + ", " +
204              durationNanos + ", NANOS)";
205        }
206    
207        private static final long serialVersionUID = 0;
208      }
209    
210      /**
211       * Returns a supplier that always supplies {@code instance}.
212       */
213      public static <T> Supplier<T> ofInstance(@Nullable T instance) {
214        return new SupplierOfInstance<T>(instance);
215      }
216    
217      private static class SupplierOfInstance<T>
218          implements Supplier<T>, Serializable {
219        final T instance;
220    
221        SupplierOfInstance(@Nullable T instance) {
222          this.instance = instance;
223        }
224    
225        
226        public T get() {
227          return instance;
228        }
229    
230        
231        @Override
232        public String toString() {
233          return "Suppliers.ofInstance(" + instance + ")";
234        }
235    
236        private static final long serialVersionUID = 0;
237      }
238    
239      /**
240       * Returns a supplier whose {@code get()} method synchronizes on
241       * {@code delegate} before calling it, making it thread-safe.
242       */
243      public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
244        return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
245      }
246    
247      private static class ThreadSafeSupplier<T>
248          implements Supplier<T>, Serializable {
249        final Supplier<T> delegate;
250    
251        ThreadSafeSupplier(Supplier<T> delegate) {
252          this.delegate = delegate;
253        }
254    
255        
256        public T get() {
257          synchronized (delegate) {
258            return delegate.get();
259          }
260        }
261    
262        
263        @Override
264        public String toString() {
265          return "Suppliers.synchronizedSupplier(" + delegate + ")";
266        }
267    
268        private static final long serialVersionUID = 0;
269      }
270    
271      /**
272       * Returns a function that accepts a supplier and returns the result of
273       * invoking {@link Supplier#get} on that supplier.
274       *
275       * @since 8.0
276       */
277      @Beta
278      @SuppressWarnings("unchecked") // SupplierFunction works for any T.
279      public static <T> Function<Supplier<T>, T> supplierFunction() {
280        return (Function) SupplierFunction.INSTANCE;
281      }
282    
283      private enum SupplierFunction implements Function<Supplier<?>, Object> {
284        INSTANCE;
285    
286        public Object apply(Supplier<?> input) {
287          return input.get();
288        }
289    
290        
291        @Override
292        public String toString() {
293          return "Suppliers.supplierFunction()";
294        }
295      }
296    }