diff --git a/RiotSharp/Caching/Cache.cs b/RiotSharp/Caching/Cache.cs index a7621758..2cda82dd 100644 --- a/RiotSharp/Caching/Cache.cs +++ b/RiotSharp/Caching/Cache.cs @@ -10,11 +10,9 @@ namespace RiotSharp.Caching /// public class Cache : ICache { - private readonly IDictionary _cache = new Dictionary(); - private readonly IDictionary _slidingTimes = new Dictionary(); + private readonly IDictionary> _cache = new Dictionary>(); private const int DefaultMonitorWait = 1000; - private const int MonitorWaitToUpdateSliding = 500; private readonly object _sync = new object(); @@ -22,7 +20,7 @@ public class Cache : ICache /// public void Add(TK key, TV value, TimeSpan slidingExpiry) where TV : class { - Add(key, value, slidingExpiry, true); + Store(key, value, slidingExpiry); } /// @@ -31,45 +29,22 @@ public void Add(TK key, TV value, DateTime absoluteExpiry) where TV : cl if (absoluteExpiry > DateTime.Now) { var diff = absoluteExpiry - DateTime.Now; - Add(key, value, diff, false); + Store(key, value, diff); } } /// public TV Get(TK key) where TV : class { - if (_cache.ContainsKey(key)) - { - var cacheItem = _cache[key]; - - if (cacheItem.RelativeExpiry.HasValue) - { - if (Monitor.TryEnter(_sync, MonitorWaitToUpdateSliding)) - { - try - { - _slidingTimes[key].Viewed(); - } - finally - { - Monitor.Exit(_sync); - } - } - } - - return (TV)cacheItem.Value; - } - - return null; + return Load(key); } - + /// public void Remove(TK key) { if (!Equals(key, null)) { _cache.Remove(key); - _slidingTimes.Remove(key); } } @@ -81,7 +56,6 @@ public void Clear() try { _cache.Clear(); - _slidingTimes.Clear(); } finally { @@ -146,7 +120,7 @@ internal IEnumerable Values() where TV : class try { return _cache.Values - .Select(cacheItem => cacheItem.Value) + .Select(cacheItem => cacheItem.Data) .Where(v => v.GetType() == typeof(TV)) .Cast().ToList(); } @@ -169,7 +143,7 @@ internal IEnumerable Values() { try { - return _cache.Values.Select(cacheItem => cacheItem.Value).ToList(); + return _cache.Values.Select(cacheItem => cacheItem.Data).ToList(); } finally { @@ -201,86 +175,48 @@ internal int Count() return -1; } - private void Add(TK key, TV value, TimeSpan timeSpan, bool isSliding) where TV : class + private TV Load(TK key) where TV : class { + CacheData data = null; if (Monitor.TryEnter(_sync, DefaultMonitorWait)) { try { - Remove(key); - _cache.Add(key, new CacheItem(value, isSliding ? timeSpan : (TimeSpan?)null)); - - if (isSliding) + CacheData objData; + this._cache.TryGetValue(key, out objData); + if (objData.Data is TV) { - _slidingTimes.Add(key, new SlidingDetails(timeSpan)); + data = objData as CacheData; } - - StartObserving(key, timeSpan); } finally { Monitor.Exit(_sync); } } - } - private void StartObserving(TK key, TimeSpan timeSpan) - { - Timer timer = null; - timer = new Timer(x => - { - TryPurgeItem(key); - timer?.Dispose(); - }, key, timeSpan, TimeSpan.FromMilliseconds(-1)); + return IsExpired(data) ? null : data.Data; } - private void TryPurgeItem(TK key) + private void Store(TK key, TV value, TimeSpan timeSpan) where TV : class { - if (_slidingTimes.ContainsKey(key)) + if (Monitor.TryEnter(_sync, DefaultMonitorWait)) { - if (!_slidingTimes[key].CanExpire(out var tryAfter)) + try { - StartObserving(key, tryAfter); - return; + Remove(key); + _cache.Add(key, new CacheData((long)timeSpan.TotalMinutes, value)); + } + finally + { + Monitor.Exit(_sync); } } - - Remove(key); - } - - private class CacheItem - { - public CacheItem(object value, TimeSpan? relativeExpiry) - { - Value = value; - RelativeExpiry = relativeExpiry; - } - - public object Value { get; } - public TimeSpan? RelativeExpiry { get; } } - private class SlidingDetails + private bool IsExpired(CacheData data) { - private readonly TimeSpan _relativeExpiry; - private DateTime _expireAt; - - public SlidingDetails(TimeSpan relativeExpiry) - { - _relativeExpiry = relativeExpiry; - Viewed(); - } - - public bool CanExpire(out TimeSpan tryAfter) - { - tryAfter = _expireAt - DateTime.Now; - return (0 > tryAfter.Ticks); - } - - public void Viewed() - { - _expireAt = DateTime.Now.Add(_relativeExpiry); - } + return data == null || DateTime.Now > data.CreatedAt.AddMinutes(data.TtlMinutes); } } }