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