using System; using System.Collections.Generic; using Unity.Collections.LowLevel.Unsafe; namespace UnityEngine.PathTracing.Core { // The type parameter T is only used as a tag, preventing different kinds of handles from being mixed together. internal readonly struct Handle { public readonly UInt64 Value; public Handle(UInt64 value) { Value = value; } public static readonly Handle Invalid = new(0xFFFFFFFFFFFFFFFF); public bool IsValid() => Value >= 0; internal int ToInt() { Debug.Assert(UnsafeUtility.SizeOf() == sizeof(int), "If this assert is firing, the size of EntityId has changed. This function should no longer be used."); return (int)Value; } // Value type semantics public override int GetHashCode() => Value.GetHashCode(); public override bool Equals(object obj) => obj is Handle other && other.Value == Value; public override string ToString() => $"Handle<{typeof(T).Name}>({Value})"; public static bool operator ==(Handle a, Handle b) => a.Value == b.Value; public static bool operator !=(Handle a, Handle b) => a.Value != b.Value; } // Keeps track of allocated instance handles. Reuses freed handles. internal class HandleSet { private readonly Stack> _freeHandles = new(); private UInt64 _nextHandleIndex; public Handle Add() { if (_freeHandles.Count > 0) return _freeHandles.Pop(); return new Handle(_nextHandleIndex++); } public void Remove(Handle handle) { Debug.Assert(!_freeHandles.Contains(handle)); _freeHandles.Push(handle); } public void Clear() { _freeHandles.Clear(); _nextHandleIndex = 0; } } }