public bool ShouldDiscard(LongTickCountLruItem <TKey, TValue> item) { if (Stopwatch.GetTimestamp() - item.TickCount > this.timeToLive) { return(true); } return(false); }
private bool GetOrDiscard(LongTickCountLruItem <TKey, TValue> item, out TValue value) { if (this.policy.ShouldDiscard(item)) { this.Move(item, ItemDestination.Remove); value = default; return(false); } value = item.Value; this.policy.Touch(item); return(true); }
public ItemDestination RouteCold(LongTickCountLruItem <TKey, TValue> item) { if (this.ShouldDiscard(item)) { return(ItemDestination.Remove); } if (item.WasAccessed) { return(ItemDestination.Warm); } return(ItemDestination.Remove); }
private void Move(LongTickCountLruItem <TKey, TValue> item, ItemDestination where) { item.WasAccessed = false; switch (where) { case ItemDestination.Warm: this.warmQueue.Enqueue(item); Interlocked.Increment(ref this.warmCount); break; case ItemDestination.Cold: this.coldQueue.Enqueue(item); Interlocked.Increment(ref this.coldCount); break; case ItemDestination.Remove: if (!item.WasRemoved) { // Avoid race where 2 threads could remove the same key - see TryRemove for details. lock (item) { if (item.WasRemoved) { break; } if (this.dictionary.TryRemove(item.Key, out LongTickCountLruItem <TKey, TValue> removedItem)) { item.WasRemoved = true; if (removedItem.Value is IDisposable d) { d.Dispose(); } } } } break; } }
/// <summary> /// Adds a key/value pair to the cache if the key does not already exist. Returns the new value, or the /// existing value if the key already exists. /// </summary> /// <param name="key">The key of the element to add.</param> /// <param name="valueFactory">The factory function used to asynchronously generate a value for the key.</param> /// <returns>A task that represents the asynchronous <see cref="GetOrAdd(TKey, Func{TKey, TValue})"/> operation.</returns> public async Task <TValue> GetOrAddAsync(TKey key, Func <TKey, Task <TValue> > valueFactory) { if (this.TryGet(key, out TValue value)) { return(value); } // The value factory may be called concurrently for the same key, but the first write to the dictionary wins. // This is identical logic in ConcurrentDictionary.GetOrAdd method. LongTickCountLruItem <TKey, TValue> newItem = this.policy.CreateItem(key, await valueFactory(key).ConfigureAwait(false)); if (this.dictionary.TryAdd(key, newItem)) { this.hotQueue.Enqueue(newItem); Interlocked.Increment(ref this.hotCount); this.Cycle(); return(newItem.Value); } return(await this.GetOrAddAsync(key, valueFactory).ConfigureAwait(false)); }
public void Touch(LongTickCountLruItem <TKey, TValue> item) { item.WasAccessed = true; }