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 017 package com.google.common.base; 018 019 import com.google.common.annotations.Beta; 020 import com.google.common.annotations.GwtCompatible; 021 import com.google.common.annotations.VisibleForTesting; 022 023 import java.io.Serializable; 024 import java.util.concurrent.TimeUnit; 025 026 import javax.annotation.Nullable; 027 028 /** 029 * Useful suppliers. 030 * 031 * <p>All methods return serializable suppliers as long as they're given 032 * serializable parameters. 033 * 034 * @author Laurence Gonsalves 035 * @author Harry Heymann 036 * @since 2.0 (imported from Google Collections Library) 037 */ 038 @GwtCompatible 039 public final class Suppliers { 040 private Suppliers() {} 041 042 /** 043 * Returns a new supplier which is the composition of the provided function 044 * and supplier. In other words, the new supplier's value will be computed by 045 * retrieving the value from {@code supplier}, and then applying 046 * {@code function} to that value. Note that the resulting supplier will not 047 * call {@code supplier} or invoke {@code function} until it is called. 048 */ 049 public static <F, T> Supplier<T> compose( 050 Function<? super F, T> function, Supplier<F> supplier) { 051 Preconditions.checkNotNull(function); 052 Preconditions.checkNotNull(supplier); 053 return new SupplierComposition<F, T>(function, supplier); 054 } 055 056 private static class SupplierComposition<F, T> 057 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 String toString() { 073 return "Suppliers.compose(" + function + ", " + supplier + ")"; 074 } 075 076 private static final long serialVersionUID = 0; 077 } 078 079 /** 080 * Returns a supplier which caches the instance retrieved during the first 081 * call to {@code get()} and returns that value on subsequent calls to 082 * {@code get()}. See: 083 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 084 * 085 * <p>The returned supplier is thread-safe. The supplier's serialized form 086 * does not contain the cached value, which will be recalculated when {@code 087 * get()} is called on the reserialized instance. 088 * 089 * <p>If {@code delegate} is an instance created by an earlier call to {@code 090 * memoize}, it is returned directly. 091 */ 092 public static <T> Supplier<T> memoize(Supplier<T> delegate) { 093 return (delegate instanceof MemoizingSupplier) 094 ? delegate 095 : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate)); 096 } 097 098 @VisibleForTesting 099 static class MemoizingSupplier<T> implements Supplier<T>, Serializable { 100 final Supplier<T> delegate; 101 transient volatile boolean initialized; 102 // "value" does not need to be volatile; visibility piggy-backs 103 // on volatile read of "initialized". 104 transient T value; 105 106 MemoizingSupplier(Supplier<T> delegate) { 107 this.delegate = delegate; 108 } 109 110 @Override 111 public T get() { 112 // A 2-field variant of Double Checked Locking. 113 if (!initialized) { 114 synchronized (this) { 115 if (!initialized) { 116 T t = delegate.get(); 117 value = t; 118 initialized = true; 119 return t; 120 } 121 } 122 } 123 return value; 124 } 125 126 @Override 127 public String toString() { 128 return "Suppliers.memoize(" + delegate + ")"; 129 } 130 131 private static final long serialVersionUID = 0; 132 } 133 134 /** 135 * Returns a supplier that caches the instance supplied by the delegate and 136 * removes the cached value after the specified time has passed. Subsequent 137 * calls to {@code get()} return the cached value if the expiration time has 138 * not passed. After the expiration time, a new value is retrieved, cached, 139 * and returned. See: 140 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 141 * 142 * <p>The returned supplier is thread-safe. The supplier's serialized form 143 * does not contain the cached value, which will be recalculated when {@code 144 * get()} is called on the reserialized instance. 145 * 146 * @param duration the length of time after a value is created that it 147 * should stop being returned by subsequent {@code get()} calls 148 * @param unit the unit that {@code duration} is expressed in 149 * @throws IllegalArgumentException if {@code duration} is not positive 150 * @since 2.0 151 */ 152 public static <T> Supplier<T> memoizeWithExpiration( 153 Supplier<T> delegate, long duration, TimeUnit unit) { 154 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); 155 } 156 157 @VisibleForTesting static class ExpiringMemoizingSupplier<T> 158 implements Supplier<T>, Serializable { 159 final Supplier<T> delegate; 160 final long durationNanos; 161 transient volatile T value; 162 // The special value 0 means "not yet initialized". 163 transient volatile long expirationNanos; 164 165 ExpiringMemoizingSupplier( 166 Supplier<T> delegate, long duration, TimeUnit unit) { 167 this.delegate = Preconditions.checkNotNull(delegate); 168 this.durationNanos = unit.toNanos(duration); 169 Preconditions.checkArgument(duration > 0); 170 } 171 172 @Override 173 public T get() { 174 // Another variant of Double Checked Locking. 175 // 176 // We use two volatile reads. We could reduce this to one by 177 // putting our fields into a holder class, but (at least on x86) 178 // the extra memory consumption and indirection are more 179 // expensive than the extra volatile reads. 180 long nanos = expirationNanos; 181 long now = Platform.systemNanoTime(); 182 if (nanos == 0 || now - nanos >= 0) { 183 synchronized (this) { 184 if (nanos == expirationNanos) { // recheck for lost race 185 T t = delegate.get(); 186 value = t; 187 nanos = now + durationNanos; 188 // In the very unlikely event that nanos is 0, set it to 1; 189 // no one will notice 1 ns of tardiness. 190 expirationNanos = (nanos == 0) ? 1 : nanos; 191 return t; 192 } 193 } 194 } 195 return value; 196 } 197 198 @Override 199 public String toString() { 200 // This is a little strange if the unit the user provided was not NANOS, 201 // but we don't want to store the unit just for toString 202 return "Suppliers.memoizeWithExpiration(" + delegate + ", " + 203 durationNanos + ", NANOS)"; 204 } 205 206 private static final long serialVersionUID = 0; 207 } 208 209 /** 210 * Returns a supplier that always supplies {@code instance}. 211 */ 212 public static <T> Supplier<T> ofInstance(@Nullable T instance) { 213 return new SupplierOfInstance<T>(instance); 214 } 215 216 private static class SupplierOfInstance<T> 217 implements Supplier<T>, Serializable { 218 final T instance; 219 220 SupplierOfInstance(@Nullable T instance) { 221 this.instance = instance; 222 } 223 224 @Override 225 public T get() { 226 return instance; 227 } 228 229 @Override 230 public String toString() { 231 return "Suppliers.ofInstance(" + instance + ")"; 232 } 233 234 private static final long serialVersionUID = 0; 235 } 236 237 /** 238 * Returns a supplier whose {@code get()} method synchronizes on 239 * {@code delegate} before calling it, making it thread-safe. 240 */ 241 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) { 242 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate)); 243 } 244 245 private static class ThreadSafeSupplier<T> 246 implements Supplier<T>, Serializable { 247 final Supplier<T> delegate; 248 249 ThreadSafeSupplier(Supplier<T> delegate) { 250 this.delegate = delegate; 251 } 252 253 @Override 254 public T get() { 255 synchronized (delegate) { 256 return delegate.get(); 257 } 258 } 259 260 @Override 261 public String toString() { 262 return "Suppliers.synchronizedSupplier(" + delegate + ")"; 263 } 264 265 private static final long serialVersionUID = 0; 266 } 267 268 /** 269 * Returns a function that accepts a supplier and returns the result of 270 * invoking {@link Supplier#get} on that supplier. 271 * 272 * @since 8.0 273 */ 274 @Beta 275 @SuppressWarnings("unchecked") // SupplierFunction works for any T. 276 public static <T> Function<Supplier<T>, T> supplierFunction() { 277 return (Function) SupplierFunction.INSTANCE; 278 } 279 280 private enum SupplierFunction implements Function<Supplier<?>, Object> { 281 INSTANCE; 282 283 @Override 284 public Object apply(Supplier<?> input) { 285 return input.get(); 286 } 287 288 @Override 289 public String toString() { 290 return "Suppliers.supplierFunction()"; 291 } 292 } 293 }