1 /* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.common.base; 18 19 import com.google.common.annotations.Beta; 20 import com.google.common.annotations.GwtCompatible; 21 import com.google.common.annotations.VisibleForTesting; 22 23 import java.io.Serializable; 24 import java.util.concurrent.TimeUnit; 25 26 import javax.annotation.Nullable; 27 28 /** 29 * Useful suppliers. 30 * 31 * <p>All methods return serializable suppliers as long as they're given 32 * serializable parameters. 33 * 34 * @author Laurence Gonsalves 35 * @author Harry Heymann 36 * @since 2.0 (imported from Google Collections Library) 37 */ 38 @GwtCompatible 39 public final class Suppliers { Suppliers()40 private Suppliers() {} 41 42 /** 43 * Returns a new supplier which is the composition of the provided function 44 * and supplier. In other words, the new supplier's value will be computed by 45 * retrieving the value from {@code supplier}, and then applying 46 * {@code function} to that value. Note that the resulting supplier will not 47 * call {@code supplier} or invoke {@code function} until it is called. 48 */ compose( Function<? super F, T> function, Supplier<F> supplier)49 public static <F, T> Supplier<T> compose( 50 Function<? super F, T> function, Supplier<F> supplier) { 51 Preconditions.checkNotNull(function); 52 Preconditions.checkNotNull(supplier); 53 return new SupplierComposition<F, T>(function, supplier); 54 } 55 56 private static class SupplierComposition<F, T> 57 implements Supplier<T>, Serializable { 58 final Function<? super F, T> function; 59 final Supplier<F> supplier; 60 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier)61 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) { 62 this.function = function; 63 this.supplier = supplier; 64 } 65 @Override get()66 public T get() { 67 return function.apply(supplier.get()); 68 } 69 private static final long serialVersionUID = 0; 70 } 71 72 /** 73 * Returns a supplier which caches the instance retrieved during the first 74 * call to {@code get()} and returns that value on subsequent calls to 75 * {@code get()}. See: 76 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 77 * 78 * <p>The returned supplier is thread-safe. The supplier's serialized form 79 * does not contain the cached value, which will be recalculated when {@code 80 * get()} is called on the reserialized instance. 81 * 82 * <p>If {@code delegate} is an instance created by an earlier call to {@code 83 * memoize}, it is returned directly. 84 */ memoize(Supplier<T> delegate)85 public static <T> Supplier<T> memoize(Supplier<T> delegate) { 86 return (delegate instanceof MemoizingSupplier) 87 ? delegate 88 : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate)); 89 } 90 91 @VisibleForTesting 92 static class MemoizingSupplier<T> implements Supplier<T>, Serializable { 93 final Supplier<T> delegate; 94 transient volatile boolean initialized; 95 // "value" does not need to be volatile; visibility piggy-backs 96 // on volatile read of "initialized". 97 transient T value; 98 MemoizingSupplier(Supplier<T> delegate)99 MemoizingSupplier(Supplier<T> delegate) { 100 this.delegate = delegate; 101 } 102 103 @Override get()104 public T get() { 105 // A 2-field variant of Double Checked Locking. 106 if (!initialized) { 107 synchronized (this) { 108 if (!initialized) { 109 T t = delegate.get(); 110 value = t; 111 initialized = true; 112 return t; 113 } 114 } 115 } 116 return value; 117 } 118 119 private static final long serialVersionUID = 0; 120 } 121 122 /** 123 * Returns a supplier that caches the instance supplied by the delegate and 124 * removes the cached value after the specified time has passed. Subsequent 125 * calls to {@code get()} return the cached value if the expiration time has 126 * not passed. After the expiration time, a new value is retrieved, cached, 127 * and returned. See: 128 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 129 * 130 * <p>The returned supplier is thread-safe. The supplier's serialized form 131 * does not contain the cached value, which will be recalculated when {@code 132 * get()} is called on the reserialized instance. 133 * 134 * @param duration the length of time after a value is created that it 135 * should stop being returned by subsequent {@code get()} calls 136 * @param unit the unit that {@code duration} is expressed in 137 * @throws IllegalArgumentException if {@code duration} is not positive 138 * @since 2.0 139 */ memoizeWithExpiration( Supplier<T> delegate, long duration, TimeUnit unit)140 public static <T> Supplier<T> memoizeWithExpiration( 141 Supplier<T> delegate, long duration, TimeUnit unit) { 142 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); 143 } 144 145 @VisibleForTesting static class ExpiringMemoizingSupplier<T> 146 implements Supplier<T>, Serializable { 147 final Supplier<T> delegate; 148 final long durationNanos; 149 transient volatile T value; 150 // The special value 0 means "not yet initialized". 151 transient volatile long expirationNanos; 152 ExpiringMemoizingSupplier( Supplier<T> delegate, long duration, TimeUnit unit)153 ExpiringMemoizingSupplier( 154 Supplier<T> delegate, long duration, TimeUnit unit) { 155 this.delegate = Preconditions.checkNotNull(delegate); 156 this.durationNanos = unit.toNanos(duration); 157 Preconditions.checkArgument(duration > 0); 158 } 159 160 @Override get()161 public T get() { 162 // Another variant of Double Checked Locking. 163 // 164 // We use two volatile reads. We could reduce this to one by 165 // putting our fields into a holder class, but (at least on x86) 166 // the extra memory consumption and indirection are more 167 // expensive than the extra volatile reads. 168 long nanos = expirationNanos; 169 long now = Platform.systemNanoTime(); 170 if (nanos == 0 || now - nanos >= 0) { 171 synchronized (this) { 172 if (nanos == expirationNanos) { // recheck for lost race 173 T t = delegate.get(); 174 value = t; 175 nanos = now + durationNanos; 176 // In the very unlikely event that nanos is 0, set it to 1; 177 // no one will notice 1 ns of tardiness. 178 expirationNanos = (nanos == 0) ? 1 : nanos; 179 return t; 180 } 181 } 182 } 183 return value; 184 } 185 186 private static final long serialVersionUID = 0; 187 } 188 189 /** 190 * Returns a supplier that always supplies {@code instance}. 191 */ ofInstance(@ullable T instance)192 public static <T> Supplier<T> ofInstance(@Nullable T instance) { 193 return new SupplierOfInstance<T>(instance); 194 } 195 196 private static class SupplierOfInstance<T> 197 implements Supplier<T>, Serializable { 198 final T instance; 199 SupplierOfInstance(@ullable T instance)200 SupplierOfInstance(@Nullable T instance) { 201 this.instance = instance; 202 } 203 @Override get()204 public T get() { 205 return instance; 206 } 207 private static final long serialVersionUID = 0; 208 } 209 210 /** 211 * Returns a supplier whose {@code get()} method synchronizes on 212 * {@code delegate} before calling it, making it thread-safe. 213 */ synchronizedSupplier(Supplier<T> delegate)214 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) { 215 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate)); 216 } 217 218 private static class ThreadSafeSupplier<T> 219 implements Supplier<T>, Serializable { 220 final Supplier<T> delegate; 221 ThreadSafeSupplier(Supplier<T> delegate)222 ThreadSafeSupplier(Supplier<T> delegate) { 223 this.delegate = delegate; 224 } 225 @Override get()226 public T get() { 227 synchronized (delegate) { 228 return delegate.get(); 229 } 230 } 231 private static final long serialVersionUID = 0; 232 } 233 234 /** 235 * Returns a function that accepts a supplier and returns the result of 236 * invoking {@link Supplier#get} on that supplier. 237 * 238 * @since 8.0 239 */ 240 @Beta 241 @SuppressWarnings("unchecked") // SupplierFunction works for any T. supplierFunction()242 public static <T> Function<Supplier<T>, T> supplierFunction() { 243 return (Function) SupplierFunction.INSTANCE; 244 } 245 246 private enum SupplierFunction implements Function<Supplier<?>, Object> { 247 INSTANCE; 248 249 @Override apply(Supplier<?> input)250 public Object apply(Supplier<?> input) { 251 return input.get(); 252 } 253 } 254 } 255