protected void SetImpl(TKey key, TValue value, TimeSpan timeToLive, long nowTicks) { var valueAndExpiryToAdd = _valueAndExpiryPool.Get(); Interlocked.Increment(ref valueAndExpiryToAdd.Version); var expiryTicks = nowTicks + (long)timeToLive.TotalMilliseconds; valueAndExpiryToAdd.Value = value; valueAndExpiryToAdd.ExpiryTicks = expiryTicks; while (true) { var valueFromCache = _values.GetOrAdd(key, valueAndExpiryToAdd); // If the value was added, we are done if (valueFromCache == valueAndExpiryToAdd) { break; } // Otherwise we need to update the value, but because we want to recycle the previous value, we need to // ensure the update only happens if the value stored is still the one we already have a reference to if (!_values.TryUpdate(key, valueAndExpiryToAdd, valueFromCache)) { continue; } // The key is already in the expiry queue, so we only need to re-add it if the new value expires before // the previous value. Otherwise, when the old expiry date is reached the key will be checked and a new // item will be put in the queue with the new expiry date var addKeyAndExpiry = expiryTicks < valueFromCache.ExpiryTicks; _valueAndExpiryPool.Return(valueFromCache); if (addKeyAndExpiry) { break; } return; } var keyAndExpiry = new KeyAndExpiry(key, expiryTicks); _keysToBePutIntoExpiryHeapWriter.TryWrite(keyAndExpiry); }
private void RemoveExpiredKey(KeyAndExpiry keyAndExpiry, long nowTicks) { if (!_values.TryGetValue(keyAndExpiry.Key, out var valueAndExpiry)) { return; } if (valueAndExpiry.ExpiryTicks < nowTicks) { var kvp = new KeyValuePair <TKey, ValueAndExpiry>(keyAndExpiry.Key, valueAndExpiry); if (((ICollection <KeyValuePair <TKey, ValueAndExpiry> >)_values).Remove(kvp)) { _valueAndExpiryPool.Return(valueAndExpiry); } } else { _keysToExpireHeap.Add(new KeyAndExpiry(keyAndExpiry.Key, valueAndExpiry.ExpiryTicks)); } }