summaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/base/Suppliers.java
diff options
context:
space:
mode:
Diffstat (limited to 'guava/src/com/google/common/base/Suppliers.java')
-rw-r--r--guava/src/com/google/common/base/Suppliers.java293
1 files changed, 293 insertions, 0 deletions
diff --git a/guava/src/com/google/common/base/Suppliers.java b/guava/src/com/google/common/base/Suppliers.java
new file mode 100644
index 0000000..add5117
--- /dev/null
+++ b/guava/src/com/google/common/base/Suppliers.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.base;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.Serializable;
+import java.util.concurrent.TimeUnit;
+
+import javax.annotation.Nullable;
+
+/**
+ * Useful suppliers.
+ *
+ * <p>All methods return serializable suppliers as long as they're given
+ * serializable parameters.
+ *
+ * @author Laurence Gonsalves
+ * @author Harry Heymann
+ * @since 2.0 (imported from Google Collections Library)
+ */
+@GwtCompatible
+public final class Suppliers {
+ private Suppliers() {}
+
+ /**
+ * Returns a new supplier which is the composition of the provided function
+ * and supplier. In other words, the new supplier's value will be computed by
+ * retrieving the value from {@code supplier}, and then applying
+ * {@code function} to that value. Note that the resulting supplier will not
+ * call {@code supplier} or invoke {@code function} until it is called.
+ */
+ public static <F, T> Supplier<T> compose(
+ Function<? super F, T> function, Supplier<F> supplier) {
+ Preconditions.checkNotNull(function);
+ Preconditions.checkNotNull(supplier);
+ return new SupplierComposition<F, T>(function, supplier);
+ }
+
+ private static class SupplierComposition<F, T>
+ implements Supplier<T>, Serializable {
+ final Function<? super F, T> function;
+ final Supplier<F> supplier;
+
+ SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
+ this.function = function;
+ this.supplier = supplier;
+ }
+
+ @Override
+ public T get() {
+ return function.apply(supplier.get());
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.compose(" + function + ", " + supplier + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a supplier which caches the instance retrieved during the first
+ * call to {@code get()} and returns that value on subsequent calls to
+ * {@code get()}. See:
+ * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
+ *
+ * <p>The returned supplier is thread-safe. The supplier's serialized form
+ * does not contain the cached value, which will be recalculated when {@code
+ * get()} is called on the reserialized instance.
+ *
+ * <p>If {@code delegate} is an instance created by an earlier call to {@code
+ * memoize}, it is returned directly.
+ */
+ public static <T> Supplier<T> memoize(Supplier<T> delegate) {
+ return (delegate instanceof MemoizingSupplier)
+ ? delegate
+ : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
+ }
+
+ @VisibleForTesting
+ static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
+ final Supplier<T> delegate;
+ transient volatile boolean initialized;
+ // "value" does not need to be volatile; visibility piggy-backs
+ // on volatile read of "initialized".
+ transient T value;
+
+ MemoizingSupplier(Supplier<T> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public T get() {
+ // A 2-field variant of Double Checked Locking.
+ if (!initialized) {
+ synchronized (this) {
+ if (!initialized) {
+ T t = delegate.get();
+ value = t;
+ initialized = true;
+ return t;
+ }
+ }
+ }
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.memoize(" + delegate + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a supplier that caches the instance supplied by the delegate and
+ * removes the cached value after the specified time has passed. Subsequent
+ * calls to {@code get()} return the cached value if the expiration time has
+ * not passed. After the expiration time, a new value is retrieved, cached,
+ * and returned. See:
+ * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
+ *
+ * <p>The returned supplier is thread-safe. The supplier's serialized form
+ * does not contain the cached value, which will be recalculated when {@code
+ * get()} is called on the reserialized instance.
+ *
+ * @param duration the length of time after a value is created that it
+ * should stop being returned by subsequent {@code get()} calls
+ * @param unit the unit that {@code duration} is expressed in
+ * @throws IllegalArgumentException if {@code duration} is not positive
+ * @since 2.0
+ */
+ public static <T> Supplier<T> memoizeWithExpiration(
+ Supplier<T> delegate, long duration, TimeUnit unit) {
+ return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
+ }
+
+ @VisibleForTesting static class ExpiringMemoizingSupplier<T>
+ implements Supplier<T>, Serializable {
+ final Supplier<T> delegate;
+ final long durationNanos;
+ transient volatile T value;
+ // The special value 0 means "not yet initialized".
+ transient volatile long expirationNanos;
+
+ ExpiringMemoizingSupplier(
+ Supplier<T> delegate, long duration, TimeUnit unit) {
+ this.delegate = Preconditions.checkNotNull(delegate);
+ this.durationNanos = unit.toNanos(duration);
+ Preconditions.checkArgument(duration > 0);
+ }
+
+ @Override
+ public T get() {
+ // Another variant of Double Checked Locking.
+ //
+ // We use two volatile reads. We could reduce this to one by
+ // putting our fields into a holder class, but (at least on x86)
+ // the extra memory consumption and indirection are more
+ // expensive than the extra volatile reads.
+ long nanos = expirationNanos;
+ long now = Platform.systemNanoTime();
+ if (nanos == 0 || now - nanos >= 0) {
+ synchronized (this) {
+ if (nanos == expirationNanos) { // recheck for lost race
+ T t = delegate.get();
+ value = t;
+ nanos = now + durationNanos;
+ // In the very unlikely event that nanos is 0, set it to 1;
+ // no one will notice 1 ns of tardiness.
+ expirationNanos = (nanos == 0) ? 1 : nanos;
+ return t;
+ }
+ }
+ }
+ return value;
+ }
+
+ @Override
+ public String toString() {
+ // This is a little strange if the unit the user provided was not NANOS,
+ // but we don't want to store the unit just for toString
+ return "Suppliers.memoizeWithExpiration(" + delegate + ", " +
+ durationNanos + ", NANOS)";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a supplier that always supplies {@code instance}.
+ */
+ public static <T> Supplier<T> ofInstance(@Nullable T instance) {
+ return new SupplierOfInstance<T>(instance);
+ }
+
+ private static class SupplierOfInstance<T>
+ implements Supplier<T>, Serializable {
+ final T instance;
+
+ SupplierOfInstance(@Nullable T instance) {
+ this.instance = instance;
+ }
+
+ @Override
+ public T get() {
+ return instance;
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.ofInstance(" + instance + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a supplier whose {@code get()} method synchronizes on
+ * {@code delegate} before calling it, making it thread-safe.
+ */
+ public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
+ return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
+ }
+
+ private static class ThreadSafeSupplier<T>
+ implements Supplier<T>, Serializable {
+ final Supplier<T> delegate;
+
+ ThreadSafeSupplier(Supplier<T> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public T get() {
+ synchronized (delegate) {
+ return delegate.get();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.synchronizedSupplier(" + delegate + ")";
+ }
+
+ private static final long serialVersionUID = 0;
+ }
+
+ /**
+ * Returns a function that accepts a supplier and returns the result of
+ * invoking {@link Supplier#get} on that supplier.
+ *
+ * @since 8.0
+ */
+ @Beta
+ @SuppressWarnings("unchecked") // SupplierFunction works for any T.
+ public static <T> Function<Supplier<T>, T> supplierFunction() {
+ return (Function) SupplierFunction.INSTANCE;
+ }
+
+ private enum SupplierFunction implements Function<Supplier<?>, Object> {
+ INSTANCE;
+
+ @Override
+ public Object apply(Supplier<?> input) {
+ return input.get();
+ }
+
+ @Override
+ public String toString() {
+ return "Suppliers.supplierFunction()";
+ }
+ }
+}