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 }