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