internal static void AddUsage(CachedResource resource, Guid usageId) { lock (UnusedResources) { resource.Usages.Add(usageId); if (resource.Usages.Count == 1 && UnusedResources.Remove(resource)) { UnusedBytes -= resource.Bytes; } } }
public static CachedResourceUsage <TResource> Get <TResource, TStream>( string group, string name, Func <Task <TStream> > getStream, Func <Stream, Task <TResource> > transform ) where TStream : Stream { var key = $"{group}:{name}"; lock (Resources) { if (Resources.TryGetValue(key, out var resource)) { return(new CachedResourceUsage <TResource>(Task.FromResult(resource))); } } return(new CachedResourceUsage <TResource>(LoadResourceAsync())); async Task <CachedResource> LoadResourceAsync() { using var stream = await getStream(); using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream); memoryStream.Position = 0; var value = await transform(memoryStream); var valueBytes = memoryStream.Length; lock (Resources) { if (!Resources.TryGetValue(key, out var resource)) { resource = Resources[key] = new CachedResource(key, value, valueBytes); } return(resource); } } }
internal static void RemoveUsage(CachedResource resource, Guid usageId) { lock (UnusedResources) { if (resource.Usages.Remove(usageId) && resource.Usages.Count == 0) { UnusedResources.Add(resource); UnusedBytes += resource.Bytes; if (UnusedBytes > UnusedBytesLimit) { // Remove least recently used resources until remaining are under the byte limit var resourcesToRemove = new List <CachedResource>(); foreach (var unusedResource in UnusedResources.OrderBy(r => r.LastAccessed)) { resourcesToRemove.Add(unusedResource); UnusedBytes -= unusedResource.Bytes; if (UnusedBytes <= UnusedBytesLimit) { break; } } lock (Resources) { foreach (var resourceToRemove in resourcesToRemove) { resourceToRemove.Dispose(); Resources.Remove(resourceToRemove.Key); UnusedResources.Remove(resourceToRemove); } } } } } }