1 /* 2 * Copyright (C) 2020 The Android Open Source Project 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 package com.android.tradefed.invoker.logger; 17 18 import javax.annotation.Nullable; 19 import javax.annotation.concurrent.ThreadSafe; 20 21 /** 22 * This class provides invocation-scope variables. 23 * 24 * <p>The mechanism operates similarly to {@link ThreadLocal}. These variables differ from their 25 * normal counterparts in that code in an invocation that accesses one (via its {@code get} method) 26 * has its own, independently initialized copy of the variable. {@code InvocationLocal} instances 27 * are typically private static fields in classes that wish to associate state with an invocation. 28 * 29 * <p>Each invocation is associated with a copy of an invocation-scoped variable as long as the 30 * invocation is in progress and the {@code InvocationLocal} instance is accessible. After an 31 * invocation is complete, all of its copies of invocation-local instances are subject to garbage 32 * collection (unless other references to these copies exist). 33 * 34 * <p>Note that unlike {@link ThreadLocal} instances that are no longer referenced while the 35 * invocation is still in progress are not garbage collected. Creating local or non-static instances 36 * is therefore not recommended as they could grow without bound. 37 * 38 * <p>Warning: Use this class sparingly as invocation-locals are glorified global variables with 39 * many of the same pitfalls. 40 */ 41 @ThreadSafe 42 public class InvocationLocal<T> { 43 /** 44 * Returns the current invocation's "initial value" for this invocation-local variable. This 45 * method will be invoked the first time code executing in the context of the invocation 46 * accesses the variable with the {@link #get} method. This method is guaranteed to be invoked 47 * at most once per invocation. 48 * 49 * <p>This implementation simply returns {@code null} but can be changed by sub-classing {@code 50 * InvocationLocal} and overriding this method. 51 * 52 * @return the initial value for this invocation-scoped variable 53 */ initialValue()54 protected @Nullable T initialValue() { 55 return null; 56 } 57 58 /** 59 * Returns the currently-executing invocation's copy of this invocation-local variable. If the 60 * variable has no value for the current invocation, it is first initialized to the value 61 * returned by a call to the {@link #initialValue} method. 62 * 63 * @return the currently executing invocation's copy of this invocation-local. 64 */ get()65 public final @Nullable T get() { 66 return CurrentInvocation.getLocal(this); 67 } 68 } 69