Files
ft/Client/Assets/Scripts/Services/PlayerData/PlayerKVGameLoadGuard.cs

44 lines
1.8 KiB
C#

using System;
using System.Threading;
namespace game.PlayerDataStorage
{
internal enum PlayerKVGuardPoint { Compare, ReadLocal, Update, Immediate, Sync, Lifecycle, PrefsSave }
internal sealed class PlayerKVLoadSideEffectException : InvalidOperationException
{ internal PlayerKVLoadSideEffectException() : base("KV controlled load rejected a legacy side effect.") { } }
internal sealed class PlayerKVGameLoadGuard : IDisposable
{
static readonly object gate=new object();
static PlayerKVGameLoadGuard owner;
readonly int[] counts=new int[7];
int violations;
bool disposed;
private PlayerKVGameLoadGuard() { }
internal static bool TryEnter(out PlayerKVGameLoadGuard lease)
{
lock(gate)
{
lease=null; if(owner!=null) return false;
owner=lease=new PlayerKVGameLoadGuard(); return true;
}
}
internal bool IsCurrent { get { lock(gate) return !disposed && ReferenceEquals(owner,this); } }
internal int Violations => Volatile.Read(ref violations);
internal int Count(PlayerKVGuardPoint point) => Volatile.Read(ref counts[(int)point]);
internal static bool Reject(PlayerKVGuardPoint point)
{
lock(gate)
{
if(owner==null) return false;
Interlocked.Increment(ref owner.counts[(int)point]); Interlocked.Increment(ref owner.violations); return true;
}
}
internal static void RequireLegacyAllowed(PlayerKVGuardPoint point)
{ if(Reject(point)) throw new PlayerKVLoadSideEffectException(); }
public void Dispose()
{
lock(gate) { if(disposed) return; disposed=true; if(ReferenceEquals(owner,this)) owner=null; }
}
}
}