android13/external/dagger2/java/dagger/producers/monitoring/ProducerMonitor.java

194 lines
7.0 KiB
Java
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2015 The Dagger Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dagger.producers.monitoring;
import static com.google.common.util.concurrent.Futures.addCallback;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListenableFuture;
import dagger.producers.Producer;
import dagger.producers.Produces;
/**
* A hook for monitoring the execution of individual {@linkplain Produces producer methods}. See
* {@link ProductionComponentMonitor} for how to install these monitors.
*
* <p>The lifecycle of the monitor, under normal conditions, is:
* <ul>
* <li>{@link #requested()}
* <li>{@link #methodStarting()}
* <li>The method is called
* <li>{@link #methodFinished()}
* <li>If the method returns a value, then:
* <ul>
* <li>{@link #succeeded(Object)} if the method returned normally; or
* <li>{@link #failed(Throwable)} if the method threw an exception.
* </ul>
* <li>If the method returns a future, then:
* <ul>
* <li>{@link #succeeded(Object)} if the method returned normally, and the future succeeded; or
* <li>{@link #failed(Throwable)} if the method threw an exception, or returned normally and the
* future failed.
* </ul>
* </ul>
*
* <p>If any input to the monitored producer fails, {@link #failed(Throwable)} will be called
* immediately with the failed input's exception. If more than one input fails, an arbitrary failed
* input's exception is used.
*
* <p>For example, given an entry point A that depends on B, which depends on C, when the entry
* point A is called, this will trigger the following sequence of events, assuming all methods and
* futures complete successfully:
* <ul>
* <li>A requested
* <li>B requested
* <li>C requested
* <li>C methodStarting
* <li>C methodFinished
* <li>C succeeded
* <li>B methodStarting
* <li>B methodFinished
* <li>B succeeded
* <li>A methodStarting
* <li>A methodFinished
* <li>A succeeded
* </ul>
*
* <p>If any of the monitor's methods throw, then the exception will be logged and processing will
* continue unaffected.
*
* @since 2.1
*/
public abstract class ProducerMonitor {
/**
* Called when the producer's output is requested; that is, when the first method is called that
* requires the production of this producer's output.
*
* <p>Note that if a method depends on {@code Producer<T>}, then this does not count as requesting
* {@code T}; that is only triggered by calling {@link Producer#get()}.
*
* <p>Depending on how this producer is requested, the following threading constraints are
* guaranteed:
*
* <ol>
* <li>If the producer is requested directly by a method on a component, then {@code requested}
* will be called on the same thread as the component method call.
* <li>If the producer is requested by value from another producer (i.e., injected as {@code T}
* or {@code Produced<T>}), then {@code requested} will be called from the same thread as
* the other producer's {@code requested}.
* <li>If the producer is requested by calling {@link Producer#get()}, then {@code requested}
* will be called from the same thread as that {@code get()} call.
* </ol>
*
* <p>When multiple monitors are installed, the order that each monitor will call this method is
* unspecified, but will remain consistent throughout the course of the execution of a component.
*
* <p>This implementation is a no-op.
*/
public void requested() {}
/**
* Called when all of the producer's inputs are available. This is called regardless of whether
* the inputs have succeeded or not; when the inputs have succeeded, this is called prior to
* scheduling the method on the executor, and if an input has failed and the producer will be
* skipped, this method will be called before {@link #failed(Throwable)} is called.
*
* <p>When multiple monitors are installed, the order that each monitor will call this method is
* unspecified, but will remain consistent throughout the course of the execution of a component.
*
* <p>This implementation is a no-op.
*/
public void ready() {}
/**
* Called when the producer method is about to start executing. This will be called from the same
* thread as the producer method itself.
*
* <p>When multiple monitors are installed, calls to this method will be in the reverse order from
* calls to {@link #requested()}.
*
* <p>This implementation is a no-op.
*/
public void methodStarting() {}
/**
* Called when the producer method has finished executing. This will be called from the same
* thread as {@link #methodStarting()} and the producer method itself.
*
* <p>When multiple monitors are installed, calls to this method will be in the reverse order from
* calls to {@link #requested()}.
*
* <p>This implementation is a no-op.
*/
public void methodFinished() {}
/**
* Called when the producers future has completed successfully with a value.
*
* <p>When multiple monitors are installed, calls to this method will be in the reverse order from
* calls to {@link #requested()}.
*
* <p>This implementation is a no-op.
*/
public void succeeded(@SuppressWarnings("unused") Object value) {}
/**
* Called when the producer's future has failed with an exception.
*
* <p>When multiple monitors are installed, calls to this method will be in the reverse order from
* calls to {@link #requested()}.
*
* <p>This implementation is a no-op.
*/
public void failed(@SuppressWarnings("unused") Throwable t) {}
/**
* Adds this monitor's completion methods as a callback to the future. This is only intended to be
* overridden in the framework!
*/
public <T> void addCallbackTo(ListenableFuture<T> future) {
addCallback(
future,
new FutureCallback<T>() {
@Override
public void onSuccess(T value) {
succeeded(value);
}
@Override
public void onFailure(Throwable t) {
failed(t);
}
},
directExecutor());
}
private static final ProducerMonitor NO_OP =
new ProducerMonitor() {
@Override
public <T> void addCallbackTo(ListenableFuture<T> future) {
// overridden to avoid adding a do-nothing callback
}
};
/** Returns a monitor that does no monitoring. */
public static ProducerMonitor noOp() {
return NO_OP;
}
}