using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; namespace Auspex.Vfx.Internal; internal sealed class FrameLifetimeTracker : IDisposable where T : IDisposable { private Dictionary<(string, string), T> prevActive; private Dictionary<(string, string), T> currActive; internal FrameLifetimeTracker() { prevActive = new Dictionary<(string, string), T>(); currActive = new Dictionary<(string, string), T>(); } internal bool IsTouched((string, string) key) { return currActive.ContainsKey(key); } internal bool TryTouchExisting((string, string) key, [MaybeNullWhen(false)] out T o) { if (prevActive.TryGetValue(key, out o)) { prevActive.Remove(key); currActive.Add(key, o); return true; } return false; } internal void TouchNew((string, string) key, T t) { currActive.Add(key, t); } internal bool Remove((string, string) key) { if (currActive.Remove(key, out var value)) { value.Dispose(); return true; } if (prevActive.Remove(key, out var value2)) { value2.Dispose(); return true; } return false; } public void Update() { foreach (KeyValuePair<(string, string), T> item in prevActive) { item.Value.Dispose(); } prevActive.Clear(); Dictionary<(string, string), T> dictionary = prevActive; prevActive = currActive; currActive = dictionary; } internal void ForEachActive(Action action) { foreach (KeyValuePair<(string, string), T> item in prevActive) { action(item.Value); } } public void Dispose() { foreach (KeyValuePair<(string, string), T> item in prevActive) { item.Value.Dispose(); } foreach (KeyValuePair<(string, string), T> item2 in currActive) { item2.Value.Dispose(); } GC.SuppressFinalize(this); } }