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.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 (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 public T get() {
066 return function.apply(supplier.get());
067 }
068 private static final long serialVersionUID = 0;
069 }
070
071 /**
072 * Returns a supplier which caches the instance retrieved during the first
073 * call to {@code get()} and returns that value on subsequent calls to
074 * {@code get()}. See:
075 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
076 *
077 * <p>The returned supplier is thread-safe. The supplier's serialized form
078 * does not contain the cached value, which will be recalculated when {@code
079 * get()} is called on the reserialized instance.
080 *
081 * <p>If {@code delegate} is an instance created by an earlier call to {@code
082 * memoize}, it is returned directly.
083 */
084 public static <T> Supplier<T> memoize(Supplier<T> delegate) {
085 return (delegate instanceof MemoizingSupplier)
086 ? delegate
087 : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate));
088 }
089
090 @VisibleForTesting
091 static class MemoizingSupplier<T> implements Supplier<T>, Serializable {
092 final Supplier<T> delegate;
093 transient volatile boolean initialized;
094 // "value" does not need to be volatile; visibility piggy-backs
095 // on volatile read of "initialized".
096 transient T value;
097
098 MemoizingSupplier(Supplier<T> delegate) {
099 this.delegate = delegate;
100 }
101
102 public T get() {
103 // A 2-field variant of Double Checked Locking.
104 if (!initialized) {
105 synchronized (this) {
106 if (!initialized) {
107 T t = delegate.get();
108 value = t;
109 initialized = true;
110 return t;
111 }
112 }
113 }
114 return value;
115 }
116
117 private static final long serialVersionUID = 0;
118 }
119
120 /**
121 * Returns a supplier that caches the instance supplied by the delegate and
122 * removes the cached value after the specified time has passed. Subsequent
123 * calls to {@code get()} return the cached value if the expiration time has
124 * not passed. After the expiration time, a new value is retrieved, cached,
125 * and returned. See:
126 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a>
127 *
128 * <p>The returned supplier is thread-safe. The supplier's serialized form
129 * does not contain the cached value, which will be recalculated when {@code
130 * get()} is called on the reserialized instance.
131 *
132 * @param duration the length of time after a value is created that it
133 * should stop being returned by subsequent {@code get()} calls
134 * @param unit the unit that {@code duration} is expressed in
135 * @throws IllegalArgumentException if {@code duration} is not positive
136 * @since 2
137 */
138 public static <T> Supplier<T> memoizeWithExpiration(
139 Supplier<T> delegate, long duration, TimeUnit unit) {
140 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit);
141 }
142
143 @VisibleForTesting static class ExpiringMemoizingSupplier<T>
144 implements Supplier<T>, Serializable {
145 final Supplier<T> delegate;
146 final long durationNanos;
147 transient volatile T value;
148 // The special value 0 means "not yet initialized".
149 transient volatile long expirationNanos;
150
151 ExpiringMemoizingSupplier(
152 Supplier<T> delegate, long duration, TimeUnit unit) {
153 this.delegate = Preconditions.checkNotNull(delegate);
154 this.durationNanos = unit.toNanos(duration);
155 Preconditions.checkArgument(duration > 0);
156 }
157
158 public T get() {
159 // Another variant of Double Checked Locking.
160 //
161 // We use two volatile reads. We could reduce this to one by
162 // putting our fields into a holder class, but (at least on x86)
163 // the extra memory consumption and indirection are more
164 // expensive than the extra volatile reads.
165 long nanos = expirationNanos;
166 long now = Platform.systemNanoTime();
167 if (nanos == 0 || now - nanos >= 0) {
168 synchronized (this) {
169 if (nanos == expirationNanos) { // recheck for lost race
170 T t = delegate.get();
171 value = t;
172 nanos = now + durationNanos;
173 // In the very unlikely event that nanos is 0, set it to 1;
174 // no one will notice 1 ns of tardiness.
175 expirationNanos = (nanos == 0) ? 1 : nanos;
176 return t;
177 }
178 }
179 }
180 return value;
181 }
182
183 private static final long serialVersionUID = 0;
184 }
185
186 /**
187 * Returns a supplier that always supplies {@code instance}.
188 */
189 public static <T> Supplier<T> ofInstance(@Nullable T instance) {
190 return new SupplierOfInstance<T>(instance);
191 }
192
193 private static class SupplierOfInstance<T>
194 implements Supplier<T>, Serializable {
195 final T instance;
196
197 SupplierOfInstance(@Nullable T instance) {
198 this.instance = instance;
199 }
200 public T get() {
201 return instance;
202 }
203 private static final long serialVersionUID = 0;
204 }
205
206 /**
207 * Returns a supplier whose {@code get()} method synchronizes on
208 * {@code delegate} before calling it, making it thread-safe.
209 */
210 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) {
211 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate));
212 }
213
214 private static class ThreadSafeSupplier<T>
215 implements Supplier<T>, Serializable {
216 final Supplier<T> delegate;
217
218 ThreadSafeSupplier(Supplier<T> delegate) {
219 this.delegate = delegate;
220 }
221 public T get() {
222 synchronized (delegate) {
223 return delegate.get();
224 }
225 }
226 private static final long serialVersionUID = 0;
227 }
228
229 /**
230 * Returns a function that accepts a supplier and returns the result of
231 * invoking {@link Supplier#get} on that supplier.
232 *
233 * @since 8
234 */
235 @Beta
236 @SuppressWarnings("unchecked") // SupplierFunction works for any T.
237 public static <T> Function<Supplier<T>, T> supplierFunction() {
238 return (Function) SupplierFunction.INSTANCE;
239 }
240
241 private enum SupplierFunction implements Function<Supplier<?>, Object> {
242 INSTANCE;
243
244 @Override
245 public Object apply(Supplier<?> input) {
246 return input.get();
247 }
248 }
249 }