using System; using System.Collections.Concurrent; using System.Threading.Tasks; namespace Wabbajack.Common; /// /// Represents a cache where values are created on-the-fly when they are found missing. /// Creating a value locks the cache entry so that each key/value pair is only created once. /// /// /// public class LazyCache where TKey : notnull { private readonly ConcurrentDictionary> _data; private readonly Func _selector; private readonly Func> _valueFactory; public LazyCache(Func selector, Func> valueFactory) { _selector = selector; _valueFactory = valueFactory; _data = new ConcurrentDictionary>(); } public async ValueTask Get(TArg lookup) { var key = _selector(lookup); while (true) { if (_data.TryGetValue(key, out var found)) return await found.Value; var value = new AsyncLazy(() => _valueFactory(lookup)); if (_data.TryAdd(key, value)) return await value.Value; } } }