Beispiel #1
0
        public async Task ReleaseAsync(DiskCacheEntry entry)
        {
            int refCount;

            // If InCache == false this is called from FinishErase with _lock already held and cause deadlock
            if (Volatile.Read(ref entry.InCache))
            {
                using (await _rwLock.WriteLockAsync())
                {
                    // entry is in "_inUse" and refcount is between 1 .. N
                    // Call Unref inside the lock to avoid other thread incrementing concurrently
                    refCount = entry.Unref();
                    if (refCount == 1)
                    {
                        // Entry is still in cache but no longer in use.
                        if (_inUse.TryRemove(entry.Key, out _))
                        {
                            _lruCache.Add(entry.Key, entry);
                        }
                    }
                    if (refCount <= 0)
                    {
                        _inUse.TryRemove(entry.Key, out _);
                        entry.Delete();
                        return;
                    }
                }
            }
            else
            {
                // its safe to decrment unref because Entry is not in cache anymore and refcount can only decrease now
                if (entry.Refs > 0)
                {
                    refCount = entry.Unref();
                    if (refCount == 0)
                    {
                        _inUse.TryRemove(entry.Key, out _);
                        entry.Delete();
                        return;
                    }
                }
            }
        }
 /// <summary>valueFactory
 /// Get item from cache of call valueFactory if missing
 /// </summary>
 /// <param name="key">The key of the value that need to be filled in</param>
 /// <param name="valueFactory">valueFactory should write result to the stream but not close it</param>
 /// <param name="ct">Cancellation token</param>
 /// <returns></returns>
 public Task <ICacheEntry> GetOrAddAsync(string key, Func <string, Stream, ICacheControl, Task> valueFactory, ICacheControl cacheControl, CancellationToken ct)
 {
     return(createEntry.DoAsync(key, async() =>
     {
         ICacheEntry found = await GetAsync(key, ct).ConfigureAwait(false);
         if (!(found is EmptyCacheEntry))
         {
             return found;
         }
         ArraySegment <byte> buffer;
         using (var memStream = new MemoryStream())
         {
             await valueFactory(key, memStream, cacheControl).ConfigureAwait(false);
             memStream.Position = 0;
             buffer = new ArraySegment <byte>(memStream.ToArray());
         }
         if (!cacheControl.NoStore)
         {
             _cache.Add(key, buffer, (ulong)buffer.Count);
         }
         return new MemoryCacheEntry(buffer);
     }));
 }