93 lines
2.7 KiB
C#
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;
|
|
}
|
|
}
|
|
} |