Files
QuartZ-dump/GlobalShared/Util/UintCache.cs
2024-12-29 21:15:58 +01:00

93 lines
2.7 KiB
C#

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using Global.Shared.Plugin;
namespace Global.Shared.Util
{
public class UintCache<TK>
{
private readonly ConcurrentDictionary<TK, ulong> cache = new ConcurrentDictionary<TK, ulong>();
private readonly ulong cleanupPeriod;
private readonly TK[] keysToDelete;
private readonly uint maxDeleteCount;
private ulong nextCleanup;
private ulong tick;
public UintCache(uint cleanupPeriod, uint maxDeleteCount = 64)
{
this.cleanupPeriod = (ulong)cleanupPeriod << 32;
this.maxDeleteCount = maxDeleteCount;
keysToDelete = new TK[this.maxDeleteCount];
nextCleanup = tick + cleanupPeriod;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Cleanup()
{
if (GlobalInstance.Plugin == null) return;
if ((tick = (ulong)GlobalInstance.Plugin.Tick << 32) < nextCleanup)
return;
nextCleanup = tick + cleanupPeriod;
var count = 0u;
foreach (var (key, item) in cache)
{
if (item >= tick)
continue;
keysToDelete[count++] = key;
if (count == maxDeleteCount)
break;
}
if (count == 0)
return;
for (var i = 0; i < count; i++)
cache.Remove(keysToDelete[i]);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Clear()
{
cache.Clear();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Store(TK key, uint value, uint lifetime)
{
var expires = tick + ((ulong)lifetime << 32);
cache[key] = expires | value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Extend(TK key, uint lifetime)
{
if (cache.TryGetValue(key, out var item))
cache[key] = (tick + ((ulong)lifetime << 32)) | (item & 0xfffffffful);
}
public void Forget(TK key)
{
cache.Remove(key);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetValue(TK key, out uint value)
{
if (cache.TryGetValue(key, out var item))
if (item >= tick)
{
value = (uint)item;
return true;
}
value = 0u;
return false;
}
}
}