001 /* 002 * Copyright (C) 2007 Google Inc. 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 (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 public T get() { 066 return function.apply(supplier.get()); 067 } 068 private static final long serialVersionUID = 0; 069 } 070 071 /** 072 * Returns a supplier which caches the instance retrieved during the first 073 * call to {@code get()} and returns that value on subsequent calls to 074 * {@code get()}. See: 075 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 076 * 077 * <p>The returned supplier is thread-safe. The supplier's serialized form 078 * does not contain the cached value, which will be recalculated when {@code 079 * get()} is called on the reserialized instance. 080 * 081 * <p>If {@code delegate} is an instance created by an earlier call to {@code 082 * memoize}, it is returned directly. 083 */ 084 public static <T> Supplier<T> memoize(Supplier<T> delegate) { 085 return (delegate instanceof MemoizingSupplier) 086 ? delegate 087 : new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate)); 088 } 089 090 @VisibleForTesting 091 static class MemoizingSupplier<T> implements Supplier<T>, Serializable { 092 final Supplier<T> delegate; 093 transient volatile boolean initialized; 094 // "value" does not need to be volatile; visibility piggy-backs 095 // on volatile read of "initialized". 096 transient T value; 097 098 MemoizingSupplier(Supplier<T> delegate) { 099 this.delegate = delegate; 100 } 101 102 public T get() { 103 // A 2-field variant of Double Checked Locking. 104 if (!initialized) { 105 synchronized (this) { 106 if (!initialized) { 107 T t = delegate.get(); 108 value = t; 109 initialized = true; 110 return t; 111 } 112 } 113 } 114 return value; 115 } 116 117 private static final long serialVersionUID = 0; 118 } 119 120 /** 121 * Returns a supplier that caches the instance supplied by the delegate and 122 * removes the cached value after the specified time has passed. Subsequent 123 * calls to {@code get()} return the cached value if the expiration time has 124 * not passed. After the expiration time, a new value is retrieved, cached, 125 * and returned. See: 126 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 127 * 128 * <p>The returned supplier is thread-safe. The supplier's serialized form 129 * does not contain the cached value, which will be recalculated when {@code 130 * get()} is called on the reserialized instance. 131 * 132 * @param duration the length of time after a value is created that it 133 * should stop being returned by subsequent {@code get()} calls 134 * @param unit the unit that {@code duration} is expressed in 135 * @throws IllegalArgumentException if {@code duration} is not positive 136 * @since 2 137 */ 138 public static <T> Supplier<T> memoizeWithExpiration( 139 Supplier<T> delegate, long duration, TimeUnit unit) { 140 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); 141 } 142 143 @VisibleForTesting static class ExpiringMemoizingSupplier<T> 144 implements Supplier<T>, Serializable { 145 final Supplier<T> delegate; 146 final long durationNanos; 147 transient volatile T value; 148 // The special value 0 means "not yet initialized". 149 transient volatile long expirationNanos; 150 151 ExpiringMemoizingSupplier( 152 Supplier<T> delegate, long duration, TimeUnit unit) { 153 this.delegate = Preconditions.checkNotNull(delegate); 154 this.durationNanos = unit.toNanos(duration); 155 Preconditions.checkArgument(duration > 0); 156 } 157 158 public T get() { 159 // Another variant of Double Checked Locking. 160 // 161 // We use two volatile reads. We could reduce this to one by 162 // putting our fields into a holder class, but (at least on x86) 163 // the extra memory consumption and indirection are more 164 // expensive than the extra volatile reads. 165 long nanos = expirationNanos; 166 long now = Platform.systemNanoTime(); 167 if (nanos == 0 || now - nanos >= 0) { 168 synchronized (this) { 169 if (nanos == expirationNanos) { // recheck for lost race 170 T t = delegate.get(); 171 value = t; 172 nanos = now + durationNanos; 173 // In the very unlikely event that nanos is 0, set it to 1; 174 // no one will notice 1 ns of tardiness. 175 expirationNanos = (nanos == 0) ? 1 : nanos; 176 return t; 177 } 178 } 179 } 180 return value; 181 } 182 183 private static final long serialVersionUID = 0; 184 } 185 186 /** 187 * Returns a supplier that always supplies {@code instance}. 188 */ 189 public static <T> Supplier<T> ofInstance(@Nullable T instance) { 190 return new SupplierOfInstance<T>(instance); 191 } 192 193 private static class SupplierOfInstance<T> 194 implements Supplier<T>, Serializable { 195 final T instance; 196 197 SupplierOfInstance(@Nullable T instance) { 198 this.instance = instance; 199 } 200 public T get() { 201 return instance; 202 } 203 private static final long serialVersionUID = 0; 204 } 205 206 /** 207 * Returns a supplier whose {@code get()} method synchronizes on 208 * {@code delegate} before calling it, making it thread-safe. 209 */ 210 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) { 211 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate)); 212 } 213 214 private static class ThreadSafeSupplier<T> 215 implements Supplier<T>, Serializable { 216 final Supplier<T> delegate; 217 218 ThreadSafeSupplier(Supplier<T> delegate) { 219 this.delegate = delegate; 220 } 221 public T get() { 222 synchronized (delegate) { 223 return delegate.get(); 224 } 225 } 226 private static final long serialVersionUID = 0; 227 } 228 229 /** 230 * Returns a function that accepts a supplier and returns the result of 231 * invoking {@link Supplier#get} on that supplier. 232 * 233 * @since 8 234 */ 235 @Beta 236 @SuppressWarnings("unchecked") // SupplierFunction works for any T. 237 public static <T> Function<Supplier<T>, T> supplierFunction() { 238 return (Function) SupplierFunction.INSTANCE; 239 } 240 241 private enum SupplierFunction implements Function<Supplier<?>, Object> { 242 INSTANCE; 243 244 @Override 245 public Object apply(Supplier<?> input) { 246 return input.get(); 247 } 248 } 249 }