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.GwtCompatible; 020 import com.google.common.annotations.VisibleForTesting; 021 022 import java.io.Serializable; 023 import java.util.concurrent.TimeUnit; 024 025 import javax.annotation.Nullable; 026 027 /** 028 * Useful suppliers. 029 * 030 * <p>All methods return serializable suppliers as long as they're given 031 * serializable parameters. 032 * 033 * @author Laurence Gonsalves 034 * @author Harry Heymann 035 * @since 2 (imported from Google Collections Library) 036 */ 037 @GwtCompatible 038 public final class Suppliers { 039 private Suppliers() {} 040 041 /** 042 * Returns a new supplier which is the composition of the provided function 043 * and supplier. In other words, the new supplier's value will be computed by 044 * retrieving the value from {@code supplier}, and then applying 045 * {@code function} to that value. Note that the resulting supplier will not 046 * call {@code supplier} or invoke {@code function} until it is called. 047 */ 048 public static <F, T> Supplier<T> compose( 049 Function<? super F, T> function, Supplier<F> supplier) { 050 Preconditions.checkNotNull(function); 051 Preconditions.checkNotNull(supplier); 052 return new SupplierComposition<F, T>(function, supplier); 053 } 054 055 private static class SupplierComposition<F, T> 056 implements Supplier<T>, Serializable { 057 final Function<? super F, T> function; 058 final Supplier<F> supplier; 059 060 SupplierComposition(Function<? super F, T> function, Supplier<F> supplier) { 061 this.function = function; 062 this.supplier = supplier; 063 } 064 public T get() { 065 return function.apply(supplier.get()); 066 } 067 private static final long serialVersionUID = 0; 068 } 069 070 /** 071 * Returns a supplier which caches the instance retrieved during the first 072 * call to {@code get()} and returns that value on subsequent calls to 073 * {@code get()}. See: 074 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 075 * 076 * <p>The returned supplier is thread-safe. The supplier's serialized form 077 * does not contain the cached value, which will be recalculated when {@code 078 * get()} is called on the reserialized instance. 079 */ 080 public static <T> Supplier<T> memoize(Supplier<T> delegate) { 081 return new MemoizingSupplier<T>(Preconditions.checkNotNull(delegate)); 082 } 083 084 @VisibleForTesting 085 static class MemoizingSupplier<T> implements Supplier<T>, Serializable { 086 final Supplier<T> delegate; 087 transient boolean initialized; 088 transient T value; 089 090 MemoizingSupplier(Supplier<T> delegate) { 091 this.delegate = delegate; 092 } 093 094 public synchronized T get() { 095 if (!initialized) { 096 value = delegate.get(); 097 initialized = true; 098 } 099 return value; 100 } 101 102 private static final long serialVersionUID = 0; 103 } 104 105 /** 106 * Returns a supplier that caches the instance supplied by the delegate and 107 * removes the cached value after the specified time has passed. Subsequent 108 * calls to {@code get()} return the cached value if the expiration time has 109 * not passed. After the expiration time, a new value is retrieved, cached, 110 * and returned. See: 111 * <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> 112 * 113 * <p>The returned supplier is thread-safe. The supplier's serialized form 114 * does not contain the cached value, which will be recalculated when {@code 115 * get()} is called on the reserialized instance. 116 * 117 * @param duration the length of time after a value is created that it 118 * should stop being returned by subsequent {@code get()} calls 119 * @param unit the unit that {@code duration} is expressed in 120 * @throws IllegalArgumentException if {@code duration} is not positive 121 * @since 2 122 */ 123 public static <T> Supplier<T> memoizeWithExpiration( 124 Supplier<T> delegate, long duration, TimeUnit unit) { 125 return new ExpiringMemoizingSupplier<T>(delegate, duration, unit); 126 } 127 128 @VisibleForTesting static class ExpiringMemoizingSupplier<T> 129 implements Supplier<T>, Serializable { 130 final Supplier<T> delegate; 131 final long durationNanos; 132 transient boolean initialized; 133 transient T value; 134 transient long expirationNanos; 135 136 ExpiringMemoizingSupplier( 137 Supplier<T> delegate, long duration, TimeUnit unit) { 138 this.delegate = Preconditions.checkNotNull(delegate); 139 this.durationNanos = unit.toNanos(duration); 140 Preconditions.checkArgument(duration > 0); 141 } 142 143 public synchronized T get() { 144 if (!initialized || Platform.systemNanoTime() - expirationNanos >= 0) { 145 value = delegate.get(); 146 initialized = true; 147 expirationNanos = Platform.systemNanoTime() + durationNanos; 148 } 149 return value; 150 } 151 152 private static final long serialVersionUID = 0; 153 } 154 155 /** 156 * Returns a supplier that always supplies {@code instance}. 157 */ 158 public static <T> Supplier<T> ofInstance(@Nullable T instance) { 159 return new SupplierOfInstance<T>(instance); 160 } 161 162 private static class SupplierOfInstance<T> 163 implements Supplier<T>, Serializable { 164 final T instance; 165 166 SupplierOfInstance(T instance) { 167 this.instance = instance; 168 } 169 public T get() { 170 return instance; 171 } 172 private static final long serialVersionUID = 0; 173 } 174 175 /** 176 * Returns a supplier whose {@code get()} method synchronizes on 177 * {@code delegate} before calling it, making it thread-safe. 178 */ 179 public static <T> Supplier<T> synchronizedSupplier(Supplier<T> delegate) { 180 return new ThreadSafeSupplier<T>(Preconditions.checkNotNull(delegate)); 181 } 182 183 private static class ThreadSafeSupplier<T> 184 implements Supplier<T>, Serializable { 185 final Supplier<T> delegate; 186 187 ThreadSafeSupplier(Supplier<T> delegate) { 188 this.delegate = delegate; 189 } 190 public T get() { 191 synchronized (delegate) { 192 return delegate.get(); 193 } 194 } 195 private static final long serialVersionUID = 0; 196 } 197 }