    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        @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.0
    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.0
    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    }