1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.supplier; 6 7 import androidx.annotation.NonNull; 8 import androidx.annotation.Nullable; 9 10 import org.chromium.base.Callback; 11 import org.chromium.base.ThreadUtils; 12 13 import java.util.ArrayList; 14 15 /** 16 * A concrete implementation of {@link SyncOneshotSupplier} to used when callbacks need to be called 17 * synchronously when a value is set. This differs from {@link OneshotSupplierImpl} in that the 18 * pending {@link Callback}s are not posted when {@link #set(T)} is invoked. 19 * 20 * <p>Instances of this class must only be accessed from the thread they were created on. 21 * 22 * <p>To use: 23 * 24 * <ol> 25 * <li>Create a new {@code SyncOneshotSupplierImpl<T>} to pass as a dependency. 26 * <li>Call {@link #set(Object)} when the object becomes available. {@link #set(Object)} may only 27 * be called once. 28 * </ol> 29 * 30 * @param <T> The type of the wrapped object. 31 */ 32 public class SyncOneshotSupplierImpl<T> implements SyncOneshotSupplier<T> { 33 private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker(); 34 35 /** Lazily created list of pending callbacks to invoke when an object is set. */ 36 private @Nullable ArrayList<Callback<T>> mPendingCallbacks; 37 38 private @Nullable T mObject; 39 40 @Override onAvailable(Callback<T> callback)41 public @Nullable T onAvailable(Callback<T> callback) { 42 mThreadChecker.assertOnValidThread(); 43 T object = get(); 44 if (object != null) { 45 callback.onResult(object); 46 } else { 47 if (mPendingCallbacks == null) { 48 mPendingCallbacks = new ArrayList<Callback<T>>(); 49 } 50 mPendingCallbacks.add(callback); 51 } 52 return object; 53 } 54 55 @Override get()56 public @Nullable T get() { 57 mThreadChecker.assertOnValidThread(); 58 return mObject; 59 } 60 61 /** 62 * Set the object supplied by this supplier. This will synchronously notify registered callbacks 63 * that the dependency is available. If {@link #set(Object)} has already been called, this 64 * method will assert. 65 * 66 * @param object The object to supply. 67 */ set(@onNull T object)68 public void set(@NonNull T object) { 69 mThreadChecker.assertOnValidThread(); 70 assert mObject == null; 71 assert object != null; 72 mObject = object; 73 if (mPendingCallbacks == null) return; 74 75 for (Callback<T> callback : mPendingCallbacks) { 76 callback.onResult(object); 77 } 78 mPendingCallbacks = null; 79 } 80 } 81