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