From c23aa1b2234c678bb52178aab4bd895a92bf8f11 Mon Sep 17 00:00:00 2001 From: DCFApixels <99481254+DCFApixels@users.noreply.github.com> Date: Fri, 11 Jul 2025 17:38:45 +0800 Subject: [PATCH] update StructList --- src/EcsWorld.static.cs | 6 +-- src/Internal/StructList.cs | 93 ++++++++++++++++++++++++++++++++++++-- src/Utils/Exceptions.cs | 6 ++- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/EcsWorld.static.cs b/src/EcsWorld.static.cs index 95be601..69722d4 100644 --- a/src/EcsWorld.static.cs +++ b/src/EcsWorld.static.cs @@ -114,7 +114,7 @@ namespace DCFApixels.DragonECS } public ReadOnlySpan GetAllWorldComponents() { - return _worldComponentPools.ToReadOnlySpan(); + return _worldComponentPools.AsReadOnlySpan(); } public abstract class WorldComponentPoolAbstract { @@ -304,7 +304,7 @@ namespace DCFApixels.DragonECS get { _worldID = _world.ID; - return _world._worldComponentPools.ToEnumerable().Skip(_world._builtinWorldComponentsCount).Select(o => o.GetRaw(_worldID)); + return _world._worldComponentPools.AsEnumerable().Skip(_world._builtinWorldComponentsCount).Select(o => o.GetRaw(_worldID)); } } public IEnumerable AllWorldComponents @@ -312,7 +312,7 @@ namespace DCFApixels.DragonECS get { _worldID = _world.ID; - return _world._worldComponentPools.ToEnumerable().Select(o => o.GetRaw(_worldID)); + return _world._worldComponentPools.AsEnumerable().Select(o => o.GetRaw(_worldID)); } } } diff --git a/src/Internal/StructList.cs b/src/Internal/StructList.cs index 1d6ad02..d146536 100644 --- a/src/Internal/StructList.cs +++ b/src/Internal/StructList.cs @@ -12,8 +12,12 @@ namespace DCFApixels.DragonECS.Core.Internal [DebuggerDisplay("Count: {Count}")] internal struct StructList { + internal readonly static bool _IsManaged = RuntimeHelpers.IsReferenceOrContainsReferences(); + internal T[] _items; internal int _count; + + #region Properties public int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -30,6 +34,11 @@ namespace DCFApixels.DragonECS.Core.Internal Array.Resize(ref _items, value); } } + public bool IsNull + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get { return _items == null; } + } public T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -49,13 +58,16 @@ namespace DCFApixels.DragonECS.Core.Internal _items[index] = value; } } + #endregion + #region Constructors [MethodImpl(MethodImplOptions.AggressiveInlining)] public StructList(int capacity) { _items = new T[ArrayUtility.NextPow2(capacity)]; _count = 0; } + #endregion [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T item) @@ -64,6 +76,11 @@ namespace DCFApixels.DragonECS.Core.Internal { Array.Resize(ref _items, _items.Length << 1); } + AddFixed(item); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void AddFixed(T item) + { _items[_count++] = item; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -72,6 +89,11 @@ namespace DCFApixels.DragonECS.Core.Internal return Array.IndexOf(_items, item, 0, _count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool Contains(T item) + { + return _count != 0 && IndexOf(item) >= 0; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SwapAt(int idnex1, int idnex2) { T tmp = _items[idnex1]; @@ -93,7 +115,10 @@ namespace DCFApixels.DragonECS.Core.Internal if (index < 0 || index >= _count) { Throw.ArgumentOutOfRange(); } #endif _items[index] = _items[--_count]; - _items[_count] = default; + if (_IsManaged) + { + _items[_count] = default; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void RemoveAtWithOrder(int index) @@ -128,6 +153,56 @@ namespace DCFApixels.DragonECS.Core.Internal } return false; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T Peek() + { +#if DEBUG + if (_count <= 0) { Throw.EmptyStack(); } +#endif + return _items[_count - 1]; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryPeek(out T result) + { + if (_count <= 0) + { + result = default; + return false; + } + result = _items[_count - 1]; + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T Pop() + { +#if DEBUG + if (_count <= 0) { Throw.EmptyStack(); } +#endif + + T result = _items[--_count]; + if (_IsManaged) + { + _items[_count] = default; + } + return result; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool TryPop(out T result) + { + if (_count <= 0) + { + result = default; + return false; + } + result = _items[--_count]; + if (_IsManaged) + { + _items[_count] = default; + } + return true; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void FastClear() { @@ -136,9 +211,9 @@ namespace DCFApixels.DragonECS.Core.Internal [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Clear() { - for (int i = 0; i < _count; i++) + if (_IsManaged) { - _items[i] = default; + Array.Clear(_items, 0, _count); } _count = 0; } @@ -148,14 +223,22 @@ namespace DCFApixels.DragonECS.Core.Internal return new ReadOnlySpan(_items, 0, _count).GetEnumerator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan ToReadOnlySpan() + public ReadOnlySpan AsReadOnlySpan() { return new ReadOnlySpan(_items, 0, _count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerable ToEnumerable() + public IEnumerable AsEnumerable() { return _items.Take(_count); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T[] ToArray() + { + if (_count <= 0) { return Array.Empty(); } + T[] result = new T[_count]; + Array.Copy(_items, result, _count); + return result; + } } } \ No newline at end of file diff --git a/src/Utils/Exceptions.cs b/src/Utils/Exceptions.cs index 04fa33a..832c41d 100644 --- a/src/Utils/Exceptions.cs +++ b/src/Utils/Exceptions.cs @@ -147,7 +147,11 @@ namespace DCFApixels.DragonECS.Core.Internal throw new ArgumentException("The groups belong to different worlds."); } - + [MethodImpl(MethodImplOptions.NoInlining)] + internal static void EmptyStack() + { + throw new InvalidOperationException("Invalid Operation Empty Stack."); + } [MethodImpl(MethodImplOptions.NoInlining)] internal static void ArgumentNull() {