using System;
using System.Collections.Generic;
namespace StardewModdingAPI.Framework.Utilities
{
/// A memory cache with sliding expiry based on custom intervals, with no background processing.
/// The cache key type.
/// The cache value type.
/// This is optimized for small caches that are reset relatively rarely. Each cache entry is marked as hot (accessed since the interval started) or stale.
/// When a new interval is started, stale entries are cleared and hot entries become stale.
internal class IntervalMemoryCache
where TKey : notnull
{
/*********
** Fields
*********/
/// The cached values that were accessed during the current interval.
private Dictionary HotCache = new();
/// The cached values that will expire on the next interval.
private Dictionary StaleCache = new();
/*********
** Public methods
*********/
/// Get a value from the cache, fetching it first if needed.
/// The unique key for the cached value.
/// Get the latest data if it's not in the cache yet.
public TValue GetOrSet(TKey cacheKey, Func get)
{
// from hot cache
if (this.HotCache.TryGetValue(cacheKey, out TValue? value))
return value;
// from stale cache
if (this.StaleCache.TryGetValue(cacheKey, out value))
{
this.HotCache[cacheKey] = value;
return value;
}
// new value
value = get();
this.HotCache[cacheKey] = value;
return value;
}
/// Start a new cache interval, removing any stale entries.
public void StartNewInterval()
{
this.StaleCache.Clear();
if (this.HotCache.Count is not 0)
(this.StaleCache, this.HotCache) = (this.HotCache, this.StaleCache); // swap hot cache to stale
}
}
}