A Provider implementation that memoizes the result of another Provider using simple lazy initialization, not the double-checked lock pattern.
| 26 | * simple lazy initialization, not the double-checked lock pattern. |
| 27 | */ |
| 28 | public final class SingleCheck<T> implements Provider<T>, Lazy<T> { |
| 29 | private static final Object UNINITIALIZED = new Object(); |
| 30 | |
| 31 | private volatile Provider<T> provider; |
| 32 | private volatile Object instance = UNINITIALIZED; |
| 33 | |
| 34 | private SingleCheck(Provider<T> provider) { |
| 35 | assert provider != null; |
| 36 | this.provider = provider; |
| 37 | } |
| 38 | |
| 39 | @SuppressWarnings("unchecked") // cast only happens when result comes from the delegate provider |
| 40 | @Override |
| 41 | public T get() { |
| 42 | // provider is volatile and might become null after the check to instance == UNINITIALIZED, so |
| 43 | // retrieve the provider first, which should not be null if instance is UNINITIALIZED. |
| 44 | // This relies upon instance also being volatile so that the reads and writes of both variables |
| 45 | // cannot be reordered. |
| 46 | Provider<T> providerReference = provider; |
| 47 | if (instance == UNINITIALIZED) { |
| 48 | instance = providerReference.get(); |
| 49 | // Null out the reference to the provider. We are never going to need it again, so we can make |
| 50 | // it eligible for GC. |
| 51 | provider = null; |
| 52 | } |
| 53 | return (T) instance; |
| 54 | } |
| 55 | |
| 56 | /** Returns a {@link Provider} that caches the value from the given delegate provider. */ |
| 57 | // This method is declared this way instead of "<T> Provider<T> provider(Provider<T> provider)" |
| 58 | // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949. |
| 59 | public static <P extends Provider<T>, T> Provider<T> provider(P provider) { |
| 60 | // If a scoped @Binds delegates to a scoped binding, don't cache the value again. |
| 61 | if (provider instanceof SingleCheck || provider instanceof DoubleCheck) { |
| 62 | return provider; |
| 63 | } |
| 64 | return new SingleCheck<T>(checkNotNull(provider)); |
| 65 | } |
| 66 | } |
nothing calls this directly
no outgoing calls
no test coverage detected