• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.producers.internal;
18 
19 import static dagger.internal.Preconditions.checkNotNull;
20 
21 import com.google.common.util.concurrent.AsyncFunction;
22 import com.google.common.util.concurrent.Futures;
23 import com.google.common.util.concurrent.ListenableFuture;
24 import dagger.producers.monitoring.ProducerMonitor;
25 import dagger.producers.monitoring.ProducerToken;
26 import dagger.producers.monitoring.ProductionComponentMonitor;
27 import java.util.concurrent.Executor;
28 import javax.inject.Provider;
29 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
30 
31 /**
32  * An {@link AbstractProducer} for all {@link dagger.producers.Produces} methods.
33  *
34  * @param <D> the type of asynchronous dependencies. These will be collected in {@link
35  *     #collectDependencies()} and then made available to the {@code @Produces method in} {@link
36  *     #callProducesMethod(Object)}. If there is only one asynchronous dependency, {@code D} can be
37  *     the key for that dependency. If there are multiple, they should be wrapped in a list and
38  *     unwrapped in {@link #callProducesMethod(Object)}.
39  * @param <T> the produced type
40  */
41 public abstract class AbstractProducesMethodProducer<D, T> extends AbstractProducer<T>
42     implements AsyncFunction<D, T>, Executor {
43   private final Provider<ProductionComponentMonitor> monitorProvider;
44   @NullableDecl private final ProducerToken token;
45   private final Provider<Executor> executorProvider;
46   private volatile ProducerMonitor monitor = null;
47 
AbstractProducesMethodProducer( Provider<ProductionComponentMonitor> monitorProvider, @NullableDecl ProducerToken token, Provider<Executor> executorProvider)48   protected AbstractProducesMethodProducer(
49       Provider<ProductionComponentMonitor> monitorProvider,
50       @NullableDecl ProducerToken token,
51       Provider<Executor> executorProvider) {
52     this.monitorProvider = checkNotNull(monitorProvider);
53     this.token = token;
54     this.executorProvider = checkNotNull(executorProvider);
55   }
56 
57   @Override
compute()58   protected final ListenableFuture<T> compute() {
59     monitor = monitorProvider.get().producerMonitorFor(token);
60     monitor.requested();
61     ListenableFuture<T> result = Futures.transformAsync(collectDependencies(), this, this);
62     monitor.addCallbackTo(result);
63     return result;
64   }
65 
66   /**
67    * Collects the asynchronous dependencies to be passed to {@link
68    * Futures#transformAsync(ListenableFuture, AsyncFunction, Executor)}.
69    */
collectDependencies()70   protected abstract ListenableFuture<D> collectDependencies();
71 
72   /** @deprecated this may only be called from the internal {@link #compute()} */
73   @Deprecated
74   @Override
apply(D asyncDependencies)75   public final ListenableFuture<T> apply(D asyncDependencies) throws Exception {
76     // NOTE(beder): We don't worry about catching exceptions from the monitor methods themselves
77     // because we'll wrap all monitoring in non-throwing monitors before we pass them to the
78     // factories.
79     monitor.methodStarting();
80     try {
81       return callProducesMethod(asyncDependencies);
82     } finally {
83       monitor.methodFinished();
84     }
85   }
86 
87   /**
88    * Calls the {@link dagger.producers.Produces} method. This will always be called on the {@link
89    * Executor} provided to this producer.
90    */
callProducesMethod(D asyncDependencies)91   protected abstract ListenableFuture<T> callProducesMethod(D asyncDependencies) throws Exception;
92 
93   /** @deprecated this may only be called from the internal {@link #compute()} */
94   @Deprecated
95   @Override
execute(Runnable runnable)96   public final void execute(Runnable runnable) {
97     monitor.ready();
98     executorProvider.get().execute(runnable);
99   }
100 }
101