• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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