Exemplo n.º 1
0
 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;
         }
     }
 }
Exemplo n.º 2
0
        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);
                }
            }
        }
Exemplo n.º 3
0
        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);
                            }
                        }
                    }
                }
            }
        }