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