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