    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    }