MCPcopy Index your code
hub / github.com/google/dagger / DoubleCheck

Class DoubleCheck

java/dagger/internal/DoubleCheck.java:28–96  ·  view source on GitHub ↗

A Lazy and Provider implementation that memoizes the value returned from a delegate using the double-check idiom described in Item 71 of Effective Java 2 .

Source from the content-addressed store, hash-verified

26 * delegate using the double-check idiom described in Item 71 of <i>Effective Java 2</i>.
27 */
28public final class DoubleCheck<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 DoubleCheck(Provider<T> provider) {
35 assert provider != null;
36 this.provider = provider;
37 }
38
39 @SuppressWarnings("unchecked") // cast only happens when result comes from the provider
40 @Override
41 public T get() {
42 Object result = instance;
43 if (result == UNINITIALIZED) {
44 synchronized (this) {
45 result = instance;
46 if (result == UNINITIALIZED) {
47 result = provider.get();
48 /* Get the current instance and test to see if the call to provider.get() has resulted
49 * in a recursive call. If it returns the same instance, we'll allow it, but if the
50 * instances differ, throw. */
51 Object currentInstance = instance;
52 if (currentInstance != UNINITIALIZED && currentInstance != result) {
53 throw new IllegalStateException("Scoped provider was invoked recursively returning "
54 + "different results: " + currentInstance + " & " + result + ". This is likely "
55 + "due to a circular dependency.");
56 }
57 instance = result;
58 /* Null out the reference to the provider. We are never going to need it again, so we
59 * can make it eligible for GC. */
60 provider = null;
61 }
62 }
63 }
64 return (T) result;
65 }
66
67 /** Returns a {@link Provider} that caches the value from the given delegate provider. */
68 // This method is declared this way instead of "<T> Provider<T> provider(Provider<T> delegate)"
69 // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949.
70 public static <P extends Provider<T>, T> Provider<T> provider(P delegate) {
71 checkNotNull(delegate);
72 if (delegate instanceof DoubleCheck) {
73 /* This should be a rare case, but if we have a scoped @Binds that delegates to a scoped
74 * binding, we shouldn't cache the value again. */
75 return delegate;
76 }
77 return new DoubleCheck<T>(delegate);
78 }
79
80 /** Returns a {@link Lazy} that caches the value from the given provider. */
81 // This method is declared this way instead of "<T> Lazy<T> lazy(Provider<T> delegate)"
82 // to work around an Eclipse type inference bug: https://github.com/google/dagger/issues/949.
83 public static <P extends Provider<T>, T> Lazy<T> lazy(P provider) {
84 if (provider instanceof Lazy) {
85 @SuppressWarnings("unchecked")

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected