1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2014 The Dagger Authors. 3*f585d8a3SJacky Wang * 4*f585d8a3SJacky Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5*f585d8a3SJacky Wang * you may not use this file except in compliance with the License. 6*f585d8a3SJacky Wang * You may obtain a copy of the License at 7*f585d8a3SJacky Wang * 8*f585d8a3SJacky Wang * http://www.apache.org/licenses/LICENSE-2.0 9*f585d8a3SJacky Wang * 10*f585d8a3SJacky Wang * Unless required by applicable law or agreed to in writing, software 11*f585d8a3SJacky Wang * distributed under the License is distributed on an "AS IS" BASIS, 12*f585d8a3SJacky Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*f585d8a3SJacky Wang * See the License for the specific language governing permissions and 14*f585d8a3SJacky Wang * limitations under the License. 15*f585d8a3SJacky Wang */ 16*f585d8a3SJacky Wang 17*f585d8a3SJacky Wang package dagger.internal; 18*f585d8a3SJacky Wang 19*f585d8a3SJacky Wang import static dagger.internal.Preconditions.checkNotNull; 20*f585d8a3SJacky Wang import static dagger.internal.Providers.asDaggerProvider; 21*f585d8a3SJacky Wang 22*f585d8a3SJacky Wang /** 23*f585d8a3SJacky Wang * A {@link Provider} implementation that memoizes the result of another {@link Provider} using 24*f585d8a3SJacky Wang * simple lazy initialization, not the double-checked lock pattern. 25*f585d8a3SJacky Wang */ 26*f585d8a3SJacky Wang public final class SingleCheck<T> implements Provider<T> { 27*f585d8a3SJacky Wang private static final Object UNINITIALIZED = new Object(); 28*f585d8a3SJacky Wang 29*f585d8a3SJacky Wang private volatile Provider<T> provider; 30*f585d8a3SJacky Wang private volatile Object instance = UNINITIALIZED; 31*f585d8a3SJacky Wang SingleCheck(Provider<T> provider)32*f585d8a3SJacky Wang private SingleCheck(Provider<T> provider) { 33*f585d8a3SJacky Wang assert provider != null; 34*f585d8a3SJacky Wang this.provider = provider; 35*f585d8a3SJacky Wang } 36*f585d8a3SJacky Wang 37*f585d8a3SJacky Wang @SuppressWarnings("unchecked") // cast only happens when result comes from the delegate provider 38*f585d8a3SJacky Wang @Override get()39*f585d8a3SJacky Wang public T get() { 40*f585d8a3SJacky Wang Object local = instance; 41*f585d8a3SJacky Wang if (local == UNINITIALIZED) { 42*f585d8a3SJacky Wang // provider is volatile and might become null after the check, so retrieve the provider first 43*f585d8a3SJacky Wang Provider<T> providerReference = provider; 44*f585d8a3SJacky Wang if (providerReference == null) { 45*f585d8a3SJacky Wang // The provider was null, so the instance must already be set 46*f585d8a3SJacky Wang local = instance; 47*f585d8a3SJacky Wang } else { 48*f585d8a3SJacky Wang local = providerReference.get(); 49*f585d8a3SJacky Wang instance = local; 50*f585d8a3SJacky Wang 51*f585d8a3SJacky Wang // Null out the reference to the provider. We are never going to need it again, so we can 52*f585d8a3SJacky Wang // make it eligible for GC. 53*f585d8a3SJacky Wang provider = null; 54*f585d8a3SJacky Wang } 55*f585d8a3SJacky Wang } 56*f585d8a3SJacky Wang return (T) local; 57*f585d8a3SJacky Wang } 58*f585d8a3SJacky Wang 59*f585d8a3SJacky Wang /** Returns a {@link Provider} that caches the value from the given delegate provider. */ 60*f585d8a3SJacky Wang // This method is declared this way instead of "<T> Provider<T> provider(Provider<T> provider)" 61*f585d8a3SJacky Wang // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949. provider(P provider)62*f585d8a3SJacky Wang public static <P extends Provider<T>, T> Provider<T> provider(P provider) { 63*f585d8a3SJacky Wang // If a scoped @Binds delegates to a scoped binding, don't cache the value again. 64*f585d8a3SJacky Wang if (provider instanceof SingleCheck || provider instanceof DoubleCheck) { 65*f585d8a3SJacky Wang return provider; 66*f585d8a3SJacky Wang } 67*f585d8a3SJacky Wang return new SingleCheck<T>(checkNotNull(provider)); 68*f585d8a3SJacky Wang } 69*f585d8a3SJacky Wang 70*f585d8a3SJacky Wang /** 71*f585d8a3SJacky Wang * Legacy javax version of the method to support libraries compiled with an older version of 72*f585d8a3SJacky Wang * Dagger. Do not use directly. 73*f585d8a3SJacky Wang */ provider( P delegate)74*f585d8a3SJacky Wang public static <P extends javax.inject.Provider<T>, T> javax.inject.Provider<T> provider( 75*f585d8a3SJacky Wang P delegate) { 76*f585d8a3SJacky Wang return provider(asDaggerProvider(delegate)); 77*f585d8a3SJacky Wang } 78*f585d8a3SJacky Wang } 79