• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {AsyncGuard} from './async_guard';
16import {okResult, Result} from './result';
17
18/**
19 * A utility class for lazily initializing and caching asynchronous values.
20 *
21 * This class ensures that a value is created only once using a provided
22 * asynchronous factory function and is cached for future access. It also
23 * provides methods to reset the cached value and retry the initialization.
24 *
25 * Internally, the class uses {@link AsyncGuard} to ensure non-overlapping of
26 * the initialization process, preventing race conditions when multiple
27 * callers attempt to initialize the value concurrently.
28 */
29export class AsyncLazy<T> {
30  private _value?: T;
31  private guard = new AsyncGuard<Result<T>>();
32
33  getOrCreate(factory: () => Promise<Result<T>>): Promise<Result<T>> {
34    if (this._value !== undefined) {
35      return Promise.resolve(okResult(this._value));
36    }
37
38    const promise = this.guard.run(factory);
39    promise.then((valueOrError) => {
40      if (valueOrError.ok) {
41        this._value = valueOrError.value;
42      }
43    });
44    return promise;
45  }
46
47  get value(): T | undefined {
48    return this._value;
49  }
50
51  reset() {
52    this._value = undefined;
53    this.guard = new AsyncGuard<Result<T>>();
54  }
55}
56