using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using NzbDrone.Common.EnsureThat; namespace NzbDrone.Common.Cache { public class Cached : ICached { private class CacheItem { public T Object { get; private set; } public DateTime? ExpiryTime { get; private set; } public CacheItem(T obj, TimeSpan? lifetime = null) { Object = obj; if (lifetime.HasValue) { ExpiryTime = DateTime.UtcNow + lifetime.Value; } } public bool IsExpired() { return ExpiryTime.HasValue && ExpiryTime.Value < DateTime.UtcNow; } } private readonly ConcurrentDictionary _store; public Cached() { _store = new ConcurrentDictionary(); } public void Set(string key, T value, TimeSpan? lifetime = null) { Ensure.That(() => key).IsNotNullOrWhiteSpace(); _store[key] = new CacheItem(value, lifetime); } public T Find(string key) { CacheItem value; _store.TryGetValue(key, out value); if (value == null) { return default(T); } if (value.IsExpired()) { _store.TryRemove(key, out value); return default(T); } return value.Object; } public T Remove(string key) { CacheItem value; _store.TryRemove(key, out value); if (value == null) { return default(T); } return value.Object; } public T Get(string key, Func function, TimeSpan? lifeTime = null) { Ensure.That(() => key).IsNotNullOrWhiteSpace(); CacheItem cacheItem; T value; if (!_store.TryGetValue(key, out cacheItem) || cacheItem.IsExpired()) { value = function(); Set(key, value, lifeTime); } else { value = cacheItem.Object; } return value; } public void Clear() { _store.Clear(); } public ICollection Values { get { return _store.Values.Select(c => c.Object).ToList(); } } } }