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.Internal.toNanosSaturated; 018import static com.google.common.base.NullnessCasts.uncheckedCastNullableTToT; 019import static com.google.common.base.Preconditions.checkArgument; 020import static com.google.common.base.Preconditions.checkNotNull; 021 022import com.google.common.annotations.GwtCompatible; 023import com.google.common.annotations.GwtIncompatible; 024import com.google.common.annotations.J2ktIncompatible; 025import com.google.common.annotations.VisibleForTesting; 026import java.io.IOException; 027import java.io.ObjectInputStream; 028import java.io.Serializable; 029import java.time.Duration; 030import java.util.concurrent.TimeUnit; 031import javax.annotation.CheckForNull; 032import org.checkerframework.checker.nullness.qual.Nullable; 033 034/** 035 * Useful suppliers. 036 * 037 * <p>All methods return serializable suppliers as long as they're given serializable parameters. 038 * 039 * @author Laurence Gonsalves 040 * @author Harry Heymann 041 * @since 2.0 042 */ 043@GwtCompatible(emulated = true) 044@ElementTypesAreNonnullByDefault 045public final class Suppliers { 046 private Suppliers() {} 047 048 /** 049 * Returns a new supplier which is the composition of the provided function and supplier. In other 050 * words, the new supplier's value will be computed by retrieving the value from {@code supplier}, 051 * and then applying {@code function} to that value. Note that the resulting supplier will not 052 * call {@code supplier} or invoke {@code function} until it is called. 053 */ 054 public static <F extends @Nullable Object, T extends @Nullable Object> Supplier<T> compose( 055 Function<? super F, T> function, Supplier<F> supplier) { 056 return new SupplierComposition<>(function, supplier); 057 } 058 059 private static class SupplierComposition<F extends @Nullable Object, T extends @Nullable Object> 060 implements Supplier<T>, Serializable { 061 final Function<? super F, T> function; 062 final Supplier<F> supplier; 063 064 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) { 065 this.function = checkNotNull(function); 066 this.supplier = checkNotNull(supplier); 067 } 068 069 @Override 070 @ParametricNullness 071 public T get() { 072 return function.apply(supplier.get()); 073 } 074 075 @Override 076 public boolean equals(@CheckForNull Object obj) { 077 if (obj instanceof SupplierComposition) { 078 SupplierComposition<?, ?> that = (SupplierComposition<?, ?>) obj; 079 return function.equals(that.function) && supplier.equals(that.supplier); 080 } 081 return false; 082 } 083 084 @Override 085 public int hashCode() { 086 return Objects.hashCode(function, supplier); 087 } 088 089 @Override 090 public String toString() { 091 return "Suppliers.compose(" + function + ", " + supplier + ")"; 092 } 093 094 private static final long serialVersionUID = 0; 095 } 096 097 /** 098 * Returns a supplier which caches the instance retrieved during the first call to {@code get()} 099 * and returns that value on subsequent calls to {@code get()}. See: <a 100 * href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 101 * 102 * <p>The returned supplier is thread-safe. The delegate's {@code get()} method will be invoked at 103 * most once unless the underlying {@code get()} throws an exception. The supplier's serialized 104 * form does not contain the cached value, which will be recalculated when {@code get()} is called 105 * on the deserialized instance. 106 * 107 * <p>When the underlying delegate throws an exception then this memoizing supplier will keep 108 * delegating calls until it returns valid data. 109 * 110 * <p>If {@code delegate} is an instance created by an earlier call to {@code memoize}, it is 111 * returned directly. 112 */ 113 public static <T extends @Nullable Object> Supplier<T> memoize(Supplier<T> delegate) { 114 if (delegate instanceof NonSerializableMemoizingSupplier 115 || delegate instanceof MemoizingSupplier) { 116 return delegate; 117 } 118 return delegate instanceof Serializable 119 ? new MemoizingSupplier<T>(delegate) 120 : new NonSerializableMemoizingSupplier<T>(delegate); 121 } 122 123 @VisibleForTesting 124 static class MemoizingSupplier<T extends @Nullable Object> implements Supplier<T>, Serializable { 125 private transient Object lock = new Object(); 126 127 final Supplier<T> delegate; 128 transient volatile boolean initialized; 129 // "value" does not need to be volatile; visibility piggy-backs 130 // on volatile read of "initialized". 131 @CheckForNull transient T value; 132 133 MemoizingSupplier(Supplier<T> delegate) { 134 this.delegate = checkNotNull(delegate); 135 } 136 137 @Override 138 @ParametricNullness 139 // We set the field only once (during construction or deserialization). 140 @SuppressWarnings("SynchronizeOnNonFinalField") 141 public T get() { 142 // A 2-field variant of Double Checked Locking. 143 if (!initialized) { 144 synchronized (lock) { 145 if (!initialized) { 146 T t = delegate.get(); 147 value = t; 148 initialized = true; 149 return t; 150 } 151 } 152 } 153 // This is safe because we checked `initialized`. 154 return uncheckedCastNullableTToT(value); 155 } 156 157 @Override 158 public String toString() { 159 return "Suppliers.memoize(" 160 + (initialized ? "<supplier that returned " + value + ">" : delegate) 161 + ")"; 162 } 163 164 @GwtIncompatible // serialization 165 @J2ktIncompatible // serialization 166 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 167 in.defaultReadObject(); 168 lock = new Object(); 169 } 170 171 private static final long serialVersionUID = 0; 172 } 173 174 @VisibleForTesting 175 static class NonSerializableMemoizingSupplier<T extends @Nullable Object> implements Supplier<T> { 176 private final Object lock = new Object(); 177 178 @SuppressWarnings("UnnecessaryLambda") // Must be a fixed singleton object 179 private static final Supplier<Void> SUCCESSFULLY_COMPUTED = 180 () -> { 181 throw new IllegalStateException(); // Should never get called. 182 }; 183 184 private volatile Supplier<T> delegate; 185 // "value" does not need to be volatile; visibility piggy-backs on volatile read of "delegate". 186 @CheckForNull private T value; 187 188 NonSerializableMemoizingSupplier(Supplier<T> delegate) { 189 this.delegate = checkNotNull(delegate); 190 } 191 192 @Override 193 @ParametricNullness 194 @SuppressWarnings("unchecked") // Cast from Supplier<Void> to Supplier<T> is always valid 195 public T get() { 196 // Because Supplier is read-heavy, we use the "double-checked locking" pattern. 197 if (delegate != SUCCESSFULLY_COMPUTED) { 198 synchronized (lock) { 199 if (delegate != SUCCESSFULLY_COMPUTED) { 200 T t = delegate.get(); 201 value = t; 202 delegate = (Supplier<T>) SUCCESSFULLY_COMPUTED; 203 return t; 204 } 205 } 206 } 207 // This is safe because we checked `delegate`. 208 return uncheckedCastNullableTToT(value); 209 } 210 211 @Override 212 public String toString() { 213 Supplier<T> delegate = this.delegate; 214 return "Suppliers.memoize(" 215 + (delegate == SUCCESSFULLY_COMPUTED 216 ? "<supplier that returned " + value + ">" 217 : delegate) 218 + ")"; 219 } 220 } 221 222 /** 223 * Returns a supplier that caches the instance supplied by the delegate and removes the cached 224 * value after the specified time has passed. Subsequent calls to {@code get()} return the cached 225 * value if the expiration time has not passed. After the expiration time, a new value is 226 * retrieved, cached, and returned. See: <a 227 * href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 228 * 229 * <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the 230 * cached value, which will be recalculated when {@code get()} is called on the reserialized 231 * instance. The actual memoization does not happen when the underlying delegate throws an 232 * exception. 233 * 234 * <p>When the underlying delegate throws an exception then this memoizing supplier will keep 235 * delegating calls until it returns valid data. 236 * 237 * @param duration the length of time after a value is created that it should stop being returned 238 * by subsequent {@code get()} calls 239 * @param unit the unit that {@code duration} is expressed in 240 * @throws IllegalArgumentException if {@code duration} is not positive 241 * @since 2.0 242 */ 243 @SuppressWarnings("GoodTime") // Prefer the Duration overload 244 public static <T extends @Nullable Object> Supplier<T> memoizeWithExpiration( 245 Supplier<T> delegate, long duration, TimeUnit unit) { 246 checkNotNull(delegate); 247 checkArgument(duration > 0, "duration (%s %s) must be > 0", duration, unit); 248 return new ExpiringMemoizingSupplier<>(delegate, unit.toNanos(duration)); 249 } 250 251 /** 252 * Returns a supplier that caches the instance supplied by the delegate and removes the cached 253 * value after the specified time has passed. Subsequent calls to {@code get()} return the cached 254 * value if the expiration time has not passed. After the expiration time, a new value is 255 * retrieved, cached, and returned. See: <a 256 * href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 257 * 258 * <p>The returned supplier is thread-safe. The supplier's serialized form does not contain the 259 * cached value, which will be recalculated when {@code get()} is called on the reserialized 260 * instance. The actual memoization does not happen when the underlying delegate throws an 261 * exception. 262 * 263 * <p>When the underlying delegate throws an exception then this memoizing supplier will keep 264 * delegating calls until it returns valid data. 265 * 266 * @param duration the length of time after a value is created that it should stop being returned 267 * by subsequent {@code get()} calls 268 * @throws IllegalArgumentException if {@code duration} is not positive 269 * @since 33.1.0 270 */ 271 @J2ktIncompatible 272 @GwtIncompatible // java.time.Duration 273 @SuppressWarnings("Java7ApiChecker") // no more dangerous that wherever the user got the Duration 274 @IgnoreJRERequirement 275 public static <T extends @Nullable Object> Supplier<T> memoizeWithExpiration( 276 Supplier<T> delegate, Duration duration) { 277 checkNotNull(delegate); 278 // The alternative of `duration.compareTo(Duration.ZERO) > 0` causes J2ObjC trouble. 279 checkArgument( 280 !duration.isNegative() && !duration.isZero(), "duration (%s) must be > 0", duration); 281 return new ExpiringMemoizingSupplier<>(delegate, toNanosSaturated(duration)); 282 } 283 284 @VisibleForTesting 285 @SuppressWarnings("GoodTime") // lots of violations 286 static class ExpiringMemoizingSupplier<T extends @Nullable Object> 287 implements Supplier<T>, Serializable { 288 private transient Object lock = new Object(); 289 290 final Supplier<T> delegate; 291 final long durationNanos; 292 @CheckForNull transient volatile T value; 293 // The special value 0 means "not yet initialized". 294 transient volatile long expirationNanos; 295 296 ExpiringMemoizingSupplier(Supplier<T> delegate, long durationNanos) { 297 this.delegate = delegate; 298 this.durationNanos = durationNanos; 299 } 300 301 @Override 302 @ParametricNullness 303 // We set the field only once (during construction or deserialization). 304 @SuppressWarnings("SynchronizeOnNonFinalField") 305 public T get() { 306 // Another variant of Double Checked Locking. 307 // 308 // We use two volatile reads. We could reduce this to one by 309 // putting our fields into a holder class, but (at least on x86) 310 // the extra memory consumption and indirection are more 311 // expensive than the extra volatile reads. 312 long nanos = expirationNanos; 313 long now = System.nanoTime(); 314 if (nanos == 0 || now - nanos >= 0) { 315 synchronized (lock) { 316 if (nanos == expirationNanos) { // recheck for lost race 317 T t = delegate.get(); 318 value = t; 319 nanos = now + durationNanos; 320 // In the very unlikely event that nanos is 0, set it to 1; 321 // no one will notice 1 ns of tardiness. 322 expirationNanos = (nanos == 0) ? 1 : nanos; 323 return t; 324 } 325 } 326 } 327 // This is safe because we checked `expirationNanos`. 328 return uncheckedCastNullableTToT(value); 329 } 330 331 @Override 332 public String toString() { 333 // This is a little strange if the unit the user provided was not NANOS, 334 // but we don't want to store the unit just for toString 335 return "Suppliers.memoizeWithExpiration(" + delegate + ", " + durationNanos + ", NANOS)"; 336 } 337 338 @GwtIncompatible // serialization 339 @J2ktIncompatible // serialization 340 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { 341 in.defaultReadObject(); 342 lock = new Object(); 343 } 344 345 private static final long serialVersionUID = 0; 346 } 347 348 /** Returns a supplier that always supplies {@code instance}. */ 349 public static <T extends @Nullable Object> Supplier<T> ofInstance( 350 @ParametricNullness T instance) { 351 return new SupplierOfInstance<>(instance); 352 } 353 354 private static class SupplierOfInstance<T extends @Nullable Object> 355 implements Supplier<T>, Serializable { 356 @ParametricNullness final T instance; 357 358 SupplierOfInstance(@ParametricNullness T instance) { 359 this.instance = instance; 360 } 361 362 @Override 363 @ParametricNullness 364 public T get() { 365 return instance; 366 } 367 368 @Override 369 public boolean equals(@CheckForNull Object obj) { 370 if (obj instanceof SupplierOfInstance) { 371 SupplierOfInstance<?> that = (SupplierOfInstance<?>) obj; 372 return Objects.equal(instance, that.instance); 373 } 374 return false; 375 } 376 377 @Override 378 public int hashCode() { 379 return Objects.hashCode(instance); 380 } 381 382 @Override 383 public String toString() { 384 return "Suppliers.ofInstance(" + instance + ")"; 385 } 386 387 private static final long serialVersionUID = 0; 388 } 389 390 /** 391 * Returns a supplier whose {@code get()} method synchronizes on {@code delegate} before calling 392 * it, making it thread-safe. 393 */ 394 @J2ktIncompatible 395 public static <T extends @Nullable Object> Supplier<T> synchronizedSupplier( 396 Supplier<T> delegate) { 397 return new ThreadSafeSupplier<>(delegate); 398 } 399 400 @J2ktIncompatible 401 private static class ThreadSafeSupplier<T extends @Nullable Object> 402 implements Supplier<T>, Serializable { 403 final Supplier<T> delegate; 404 405 ThreadSafeSupplier(Supplier<T> delegate) { 406 this.delegate = checkNotNull(delegate); 407 } 408 409 @Override 410 @ParametricNullness 411 public T get() { 412 synchronized (delegate) { 413 return delegate.get(); 414 } 415 } 416 417 @Override 418 public String toString() { 419 return "Suppliers.synchronizedSupplier(" + delegate + ")"; 420 } 421 422 private static final long serialVersionUID = 0; 423 } 424 425 /** 426 * Returns a function that accepts a supplier and returns the result of invoking {@link 427 * Supplier#get} on that supplier. 428 * 429 * <p><b>Java 8+ users:</b> use the method reference {@code Supplier::get} instead. 430 * 431 * @since 8.0 432 */ 433 public static <T extends @Nullable Object> Function<Supplier<T>, T> supplierFunction() { 434 @SuppressWarnings("unchecked") // implementation is "fully variant" 435 SupplierFunction<T> sf = (SupplierFunction<T>) SupplierFunctionImpl.INSTANCE; 436 return sf; 437 } 438 439 private interface SupplierFunction<T extends @Nullable Object> extends Function<Supplier<T>, T> {} 440 441 private enum SupplierFunctionImpl implements SupplierFunction<@Nullable Object> { 442 INSTANCE; 443 444 // Note: This makes T a "pass-through type" 445 @Override 446 @CheckForNull 447 public Object apply(Supplier<@Nullable Object> input) { 448 return input.get(); 449 } 450 451 @Override 452 public String toString() { 453 return "Suppliers.supplierFunction()"; 454 } 455 } 456}