001/* 002 * Copyright (C) 2007 The Guava Authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 005 * in compliance with the License. You may obtain a copy of the License at 006 * 007 * http://www.apache.org/licenses/LICENSE-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, software distributed under the License 010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 011 * or implied. See the License for the specific language governing permissions and limitations under 012 * the License. 013 */ 014 015package com.google.common.base; 016 017import static com.google.common.base.NullnessCasts.uncheckedCastNullableTToT; 018import static com.google.common.base.Preconditions.checkArgument; 019import static com.google.common.base.Preconditions.checkNotNull; 020import static java.util.Objects.requireNonNull; 021 022import com.google.common.annotations.GwtCompatible; 023import com.google.common.annotations.VisibleForTesting; 024import java.io.Serializable; 025import java.util.concurrent.TimeUnit; 026import javax.annotation.CheckForNull; 027import org.checkerframework.checker.nullness.qual.Nullable; 028 029/** 030 * Useful suppliers. 031 * 032 * <p>All methods return serializable suppliers as long as they're given serializable parameters. 033 * 034 * @author Laurence Gonsalves 035 * @author Harry Heymann 036 * @since 2.0 037 */ 038@GwtCompatible 039@ElementTypesAreNonnullByDefault 040public final class Suppliers { 041 private Suppliers() {} 042 043 /** 044 * Returns a new supplier which is the composition of the provided function and supplier. In other 045 * words, the new supplier's value will be computed by retrieving the value from {@code supplier}, 046 * and then applying {@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 extends @Nullable Object, T extends @Nullable Object> Supplier<T> compose( 050 Function<? super F, T> function, Supplier<F> supplier) { 051 return new SupplierComposition<>(function, supplier); 052 } 053 054 private static class SupplierComposition<F extends @Nullable Object, T extends @Nullable Object> 055 implements Supplier<T>, Serializable { 056 final Function<? super F, T> function; 057 final Supplier<F> supplier; 058 059 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) { 060 this.function = checkNotNull(function); 061 this.supplier = checkNotNull(supplier); 062 } 063 064 @Override 065 @ParametricNullness 066 public T get() { 067 return function.apply(supplier.get()); 068 } 069 070 @Override 071 public boolean equals(@CheckForNull Object obj) { 072 if (obj instanceof SupplierComposition) { 073 SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj; 074 return function.equals(that.function) && supplier.equals(that.supplier); 075 } 076 return false; 077 } 078 079 @Override 080 public int hashCode() { 081 return Objects.hashCode(function, supplier); 082 } 083 084 @Override 085 public String toString() { 086 return "Suppliers.compose(" + function + ", " + supplier + ")"; 087 } 088 089 private static final long serialVersionUID = 0; 090 } 091 092 /** 093 * Returns a supplier which caches the instance retrieved during the first call to {@code get()} 094 * and returns that value on subsequent calls to {@code get()}. See: <a 095 * href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 096 * 097 * <p>The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at 098 * most once unless the underlying {@code get()} throws an exception. The supplier's serialized 099 * form does not contain the cached value, which will be recalculated when {@code get()} is called 100 * on the reserialized instance. 101 * 102 * <p>When the underlying delegate throws an exception then this memoizing supplier will keep 103 * delegating calls until it returns valid data. 104 * 105 * <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is 106 * returned directly. 107 */ 108 public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) { 109 if (delegate instanceof NonSerializableMemoizingSupplier 110 || delegate instanceof MemoizingSupplier) { 111 return delegate; 112 } 113 return delegate instanceof Serializable 114 ? new MemoizingSupplier<T>(delegate) 115 : new NonSerializableMemoizingSupplier<T>(delegate); 116 } 117 118 @VisibleForTesting 119 static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T>, Serializable { 120 final Supplier<T> delegate; 121 transient volatile boolean initialized; 122 // "value" does not need to be volatile; visibility piggy-backs 123 // on volatile read of "initialized". 124 @CheckForNull transient T value; 125 126 MemoizingSupplier(Supplier<T> delegate) { 127 this.delegate = checkNotNull(delegate); 128 } 129 130 @Override 131 @ParametricNullness 132 public T get() { 133 // A 2-field variant of Double Checked Locking. 134 if (!initialized) { 135 synchronized (this) { 136 if (!initialized) { 137 T t = delegate.get(); 138 value = t; 139 initialized = true; 140 return t; 141 } 142 } 143 } 144 // This is safe because we checked `initialized.` 145 return uncheckedCastNullableTToT(value); 146 } 147 148 @Override 149 public String toString() { 150 return "Suppliers.memoize(" 151 + (initialized ? "<supplier that returned " + value + ">" : delegate) 152 + ")"; 153 } 154 155 private static final long serialVersionUID = 0; 156 } 157 158 @VisibleForTesting 159 static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> { 160 @CheckForNull volatile Supplier<T> delegate; 161 volatile boolean initialized; 162 // "value" does not need to be volatile; visibility piggy-backs 163 // on volatile read of "initialized". 164 @CheckForNull T value; 165 166 NonSerializableMemoizingSupplier(Supplier<T> delegate) { 167 this.delegate = checkNotNull(delegate); 168 } 169 170 @Override 171 @ParametricNullness 172 public T get() { 173 // A 2-field variant of Double Checked Locking. 174 if (!initialized) { 175 synchronized (this) { 176 if (!initialized) { 177 /* 178 * requireNonNull is safe because we read and write `delegate` under synchronization. 179 * 180 * TODO(cpovirk): To avoid having to check for null, replace `delegate` with a singleton 181 * `Supplier` that always throws an exception. 182 */ 183 T t = requireNonNull(delegate).get(); 184 value = t; 185 initialized = true; 186 // Release the delegate to GC. 187 delegate = null; 188 return t; 189 } 190 } 191 } 192 // This is safe because we checked `initialized.` 193 return uncheckedCastNullableTToT(value); 194 } 195 196 @Override 197 public String toString() { 198 Supplier<T> delegate = this.delegate; 199 return "Suppliers.memoize(" 200 + (delegate == null ? "<supplier that returned " + value + ">" : delegate) 201 + ")"; 202 } 203 } 204 205 /** 206 * Returns a supplier that caches the instance supplied by the delegate and removes the cached 207 * value after the specified time has passed. Subsequent calls to {@code get()} return the cached 208 * value if the expiration time has not passed. After the expiration time, a new value is 209 * retrieved, cached, and returned. See: <a 210 * href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 211 * 212 * <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the 213 * cached value, which will be recalculated when {@code get()} is called on the reserialized 214 * instance. The actual memoization does not happen when the underlying delegate throws an 215 * exception. 216 * 217 * <p>When the underlying delegate throws an exception then this memoizing supplier will keep 218 * delegating calls until it returns valid data. 219 * 220 * @param duration the length of time after a value is created that it should stop being returned 221 * by subsequent {@code get()} calls 222 * @param unit the unit that {@code duration} is expressed in 223 * @throws IllegalArgumentException if {@code duration} is not positive 224 * @since 2.0 225 */ 226 @SuppressWarnings("GoodTime") // should accept a java.time.Duration 227 public static <T extends @Nullable Object> Supplier<T> memoizeWithExpiration( 228 Supplier<T> delegate, long duration, TimeUnit unit) { 229 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); 230 } 231 232 @VisibleForTesting 233 @SuppressWarnings("GoodTime") // lots of violations 234 static class ExpiringMemoizingSupplier<T extends @Nullable Object> 235 implements Supplier<T>, Serializable { 236 final Supplier<T> delegate; 237 final long durationNanos; 238 @CheckForNull transient volatile T value; 239 // The special value 0 means "not yet initialized". 240 transient volatile long expirationNanos; 241 242 ExpiringMemoizingSupplier(Supplier<T> delegate, long duration, TimeUnit unit) { 243 this.delegate = checkNotNull(delegate); 244 this.durationNanos = unit.toNanos(duration); 245 checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit); 246 } 247 248 @Override 249 @ParametricNullness 250 public T get() { 251 // Another variant of Double Checked Locking. 252 // 253 // We use two volatile reads. We could reduce this to one by 254 // putting our fields into a holder class, but (at least on x86) 255 // the extra memory consumption and indirection are more 256 // expensive than the extra volatile reads. 257 long nanos = expirationNanos; 258 long now = Platform.systemNanoTime(); 259 if (nanos == 0 || now - nanos >= 0) { 260 synchronized (this) { 261 if (nanos == expirationNanos) { // recheck for lost race 262 T t = delegate.get(); 263 value = t; 264 nanos = now + durationNanos; 265 // In the very unlikely event that nanos is 0, set it to 1; 266 // no one will notice 1 ns of tardiness. 267 expirationNanos = (nanos == 0) ? 1 : nanos; 268 return t; 269 } 270 } 271 } 272 // This is safe because we checked `expirationNanos.` 273 return uncheckedCastNullableTToT(value); 274 } 275 276 @Override 277 public String toString() { 278 // This is a little strange if the unit the user provided was not NANOS, 279 // but we don't want to store the unit just for toString 280 return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)"; 281 } 282 283 private static final long serialVersionUID = 0; 284 } 285 286 /** Returns a supplier that always supplies {@code instance}. */ 287 public static <T extends @Nullable Object> Supplier<T> ofInstance( 288 @ParametricNullness T instance) { 289 return new SupplierOfInstance<T>(instance); 290 } 291 292 private static class SupplierOfInstance<T extends @Nullable Object> 293 implements Supplier<T>, Serializable { 294 @ParametricNullness final T instance; 295 296 SupplierOfInstance(@ParametricNullness T instance) { 297 this.instance = instance; 298 } 299 300 @Override 301 @ParametricNullness 302 public T get() { 303 return instance; 304 } 305 306 @Override 307 public boolean equals(@CheckForNull Object obj) { 308 if (obj instanceof SupplierOfInstance) { 309 SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj; 310 return Objects.equal(instance, that.instance); 311 } 312 return false; 313 } 314 315 @Override 316 public int hashCode() { 317 return Objects.hashCode(instance); 318 } 319 320 @Override 321 public String toString() { 322 return "Suppliers.ofInstance(" + instance + ")"; 323 } 324 325 private static final long serialVersionUID = 0; 326 } 327 328 /** 329 * Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling 330 * it, making it thread-safe. 331 */ 332 public static <T extends @Nullable Object> Supplier<T> synchronizedSupplier( 333 Supplier<T> delegate) { 334 return new ThreadSafeSupplier<T>(delegate); 335 } 336 337 private static class ThreadSafeSupplier<T extends @Nullable Object> 338 implements Supplier<T>, Serializable { 339 final Supplier<T> delegate; 340 341 ThreadSafeSupplier(Supplier<T> delegate) { 342 this.delegate = checkNotNull(delegate); 343 } 344 345 @Override 346 @ParametricNullness 347 public T get() { 348 synchronized (delegate) { 349 return delegate.get(); 350 } 351 } 352 353 @Override 354 public String toString() { 355 return "Suppliers.synchronizedSupplier(" + delegate + ")"; 356 } 357 358 private static final long serialVersionUID = 0; 359 } 360 361 /** 362 * Returns a function that accepts a supplier and returns the result of invoking {@link 363 * Supplier#get} on that supplier. 364 * 365 * <p><b>Java 8 users:</b> use the method reference {@code Supplier::get} instead. 366 * 367 * @since 8.0 368 */ 369 public static <T extends @Nullable Object> Function<Supplier<T>, T> supplierFunction() { 370 @SuppressWarnings("unchecked") // implementation is "fully variant" 371 SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE; 372 return sf; 373 } 374 375 private interface SupplierFunction<T extends @Nullable Object> extends Function<Supplier<T>, T> {} 376 377 private enum SupplierFunctionImpl implements SupplierFunction<@Nullable Object> { 378 INSTANCE; 379 380 // Note: This makes T a "pass-through type" 381 @Override 382 @CheckForNull 383 public Object apply(Supplier<@Nullable Object> input) { 384 return input.get(); 385 } 386 387 @Override 388 public String toString() { 389 return "Suppliers.supplierFunction()"; 390 } 391 } 392}