001 /*
002 * Copyright (C) 2007 Google Inc.
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.GwtCompatible;
020 import com.google.common.annotations.VisibleForTesting;
021
022 import java.io.Serializable;
023 import java.util.concurrent.TimeUnit;
024
025 import javax.annotation.Nullable;
026
027 /**
028 * Useful suppliers.
029 *
030 * <p>All methods return serializable suppliers as long as they're given
031 * serializable parameters.
032 *
033 * @author Laurence Gonsalves
034 * @author Harry Heymann
035 * @since 2 (imported from Google Collections Library)
036 */
037 @GwtCompatible
038 public final class Suppliers {
039 private Suppliers() {}
040
041 /**
042 * Returns a new supplier which is the composition of the provided function
043 * and supplier. In other words, the new supplier's value will be computed by
044 * retrieving the value from {@code supplier}, and then applying
045 * {@code function} to that value. Note that the resulting supplier will not
046 * call {@code supplier} or invoke {@code function} until it is called.
047 */
048 public static <F, T> Supplier<T> compose(
049 Function<? super F, T> function, Supplier<F> supplier) {
050 Preconditions.checkNotNull(function);
051 Preconditions.checkNotNull(supplier);
052 return new SupplierComposition<F, T>(function, supplier);
053 }
054
055 private static class SupplierComposition<F, T>
056 implements Supplier<T>, Serializable {
057 final Function<? super F, T> function;
058 final Supplier<F> supplier;
059
060 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) {
061 this.function = function;
062 this.supplier = supplier;
063 }
064 public T get() {
065 return function.apply(supplier.get());
066 }
067 private static final long serialVersionUID = 0;
068 }
069
070 /**
071 * Returns a supplier which caches the instance retrieved during the first
072 * call to {@code get()} and returns that value on subsequent calls to
073 * {@code get()}. See:
074 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
075 *
076 * <p>The returned supplier is thread-safe. The supplier's serialized form
077 * does not contain the cached value, which will be recalculated when {@code
078 * get()} is called on the reserialized instance.
079 */
080 public static <T> Supplier<T> memoize(Supplier<T> delegate) {
081 return new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
082 }
083
084 @VisibleForTesting
085 static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
086 final Supplier<T> delegate;
087 transient boolean initialized;
088 transient T value;
089
090 MemoizingSupplier(Supplier<T> delegate) {
091 this.delegate = delegate;
092 }
093
094 public synchronized T get() {
095 if (!initialized) {
096 value = delegate.get();
097 initialized = true;
098 }
099 return value;
100 }
101
102 private static final long serialVersionUID = 0;
103 }
104
105 /**
106 * Returns a supplier that caches the instance supplied by the delegate and
107 * removes the cached value after the specified time has passed. Subsequent
108 * calls to {@code get()} return the cached value if the expiration time has
109 * not passed. After the expiration time, a new value is retrieved, cached,
110 * and returned. See:
111 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
112 *
113 * <p>The returned supplier is thread-safe. The supplier's serialized form
114 * does not contain the cached value, which will be recalculated when {@code
115 * get()} is called on the reserialized instance.
116 *
117 * @param duration the length of time after a value is created that it
118 * should stop being returned by subsequent {@code get()} calls
119 * @param unit the unit that {@code duration} is expressed in
120 * @throws IllegalArgumentException if {@code duration} is not positive
121 * @since 2
122 */
123 public static <T> Supplier<T> memoizeWithExpiration(
124 Supplier<T> delegate, long duration, TimeUnit unit) {
125 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
126 }
127
128 @VisibleForTesting static class ExpiringMemoizingSupplier<T>
129 implements Supplier<T>, Serializable {
130 final Supplier<T> delegate;
131 final long durationNanos;
132 transient boolean initialized;
133 transient T value;
134 transient long expirationNanos;
135
136 ExpiringMemoizingSupplier(
137 Supplier<T> delegate, long duration, TimeUnit unit) {
138 this.delegate = Preconditions.checkNotNull(delegate);
139 this.durationNanos = unit.toNanos(duration);
140 Preconditions.checkArgument(duration > 0);
141 }
142
143 public synchronized T get() {
144 if (!initialized || Platform.systemNanoTime() - expirationNanos >= 0) {
145 value = delegate.get();
146 initialized = true;
147 expirationNanos = Platform.systemNanoTime() + durationNanos;
148 }
149 return value;
150 }
151
152 private static final long serialVersionUID = 0;
153 }
154
155 /**
156 * Returns a supplier that always supplies {@code instance}.
157 */
158 public static <T> Supplier<T> ofInstance(@Nullable T instance) {
159 return new SupplierOfInstance<T>(instance);
160 }
161
162 private static class SupplierOfInstance<T>
163 implements Supplier<T>, Serializable {
164 final T instance;
165
166 SupplierOfInstance(T instance) {
167 this.instance = instance;
168 }
169 public T get() {
170 return instance;
171 }
172 private static final long serialVersionUID = 0;
173 }
174
175 /**
176 * Returns a supplier whose {@code get()} method synchronizes on
177 * {@code delegate} before calling it, making it thread-safe.
178 */
179 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
180 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
181 }
182
183 private static class ThreadSafeSupplier<T>
184 implements Supplier<T>, Serializable {
185 final Supplier<T> delegate;
186
187 ThreadSafeSupplier(Supplier<T> delegate) {
188 this.delegate = delegate;
189 }
190 public T get() {
191 synchronized (delegate) {
192 return delegate.get();
193 }
194 }
195 private static final long serialVersionUID = 0;
196 }
197 }