diff --git a/Misaki.HighPerformance.LowLevel/Misaki.HighPerformance.LowLevel.csproj b/Misaki.HighPerformance.LowLevel/Misaki.HighPerformance.LowLevel.csproj index 611e7c2..a289b17 100644 --- a/Misaki.HighPerformance.LowLevel/Misaki.HighPerformance.LowLevel.csproj +++ b/Misaki.HighPerformance.LowLevel/Misaki.HighPerformance.LowLevel.csproj @@ -7,7 +7,7 @@ true true Misaki - 1.3.8 + 1.3.9 $(AssemblyVersion) https://git.personalnas.com/Misaki/Misaki.HighPerformance.git https://git.personalnas.com/Misaki/Misaki.HighPerformance.git diff --git a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Utilities/HashMapHelper.cs b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/HashMapHelper.cs similarity index 99% rename from Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Utilities/HashMapHelper.cs rename to Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/HashMapHelper.cs index 3be76d4..ac3c96f 100644 --- a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Utilities/HashMapHelper.cs +++ b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/HashMapHelper.cs @@ -1,10 +1,10 @@ using Misaki.HighPerformance.LowLevel.Buffer; -using Misaki.HighPerformance.LowLevel.Collections; +using Misaki.HighPerformance.LowLevel.Utilities; using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; -namespace Misaki.HighPerformance.LowLevel.Utilities; +namespace Misaki.HighPerformance.LowLevel.Collections; public unsafe struct HashMapHelper : IDisposable where TKey : unmanaged, IEquatable diff --git a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeList.cs b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeList.cs index 79c4871..4b8a5c5 100644 --- a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeList.cs +++ b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeList.cs @@ -79,6 +79,8 @@ public unsafe struct UnsafeList : IUnsafeCollection /// public unsafe struct ParallelWriter { + private volatile int _resizeLock; + /// /// The UnsafeList to write to. /// @@ -259,22 +261,20 @@ public unsafe struct UnsafeList : IUnsafeCollection /// Adds a range of elements to the collection. /// /// A span containing the elements to add. The span must not exceed the specified . - /// The number of elements to add from the span. Must be non-negative and less than or - /// equal to the length of . - public void AddRange(Span values, int count) + public void AddRange(Span values) { - var newSize = _count + count; + var newSize = _count + values.Length; if (newSize > Capacity) { - Resize(Capacity + count); + Resize(Capacity + values.Length); } fixed (T* ptr = values) { - MemCpy(UnsafeUtility.ReadArrayElementUnsafe(_array.GetUnsafePtr(), _count), ptr, (uint)(count * sizeof(T))); + MemCpy(UnsafeUtility.ReadArrayElementUnsafe(_array.GetUnsafePtr(), _count), ptr, (uint)(values.Length * sizeof(T))); } - _count += count; + _count += values.Length; } /// diff --git a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSlotMap.cs b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSlotMap.cs index ecd0f3a..c8a11d9 100644 --- a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSlotMap.cs +++ b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSlotMap.cs @@ -176,11 +176,12 @@ public unsafe struct UnsafeSlotMap : IUnsafeCollection /// Attempts to remove the item at the specified slot index and generation from the collection. /// /// The zero-based index of the slot to remove. Must be within the valid range of slot indices. - /// The generation value associated with the slot. Removal succeeds only if this matches the current generation of - /// the slot. + /// The generation value associated with the slot. Removal succeeds only if this matches the current generation of the slot. + /// When this method returns, contains the item that was removed if the removal was successful; otherwise, the default value for type . /// true if the item was successfully removed; otherwise, false. - public bool Remove(int slotIndex, int generation) + public bool Remove(int slotIndex, int generation, out T item) { + item = default; if (slotIndex < 0 || slotIndex >= _capacity) { return false; @@ -192,6 +193,8 @@ public unsafe struct UnsafeSlotMap : IUnsafeCollection return false; } + item = _data[slotIndex]; + gen++; _validBits.ClearBit(slotIndex); _freeSlots.Enqueue(slotIndex); @@ -201,6 +204,18 @@ public unsafe struct UnsafeSlotMap : IUnsafeCollection return true; } + /// + /// Attempts to remove the item at the specified slot index and generation from the collection. + /// + /// The zero-based index of the slot to remove. Must be within the valid range of slot indices. + /// The generation value associated with the slot. Removal succeeds only if this matches the current generation of + /// the slot. + /// true if the item was successfully removed; otherwise, false. + public bool Remove(int slotIndex, int generation) + { + return Remove(slotIndex, generation, out _); + } + /// /// Determines whether the specified slot index contains a valid entry with the given generation. /// diff --git a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSparseSet.cs b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSparseSet.cs index e8bb1ca..282db52 100644 --- a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSparseSet.cs +++ b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/Collections/UnsafeSparseSet.cs @@ -190,6 +190,49 @@ public unsafe struct UnsafeSparseSet : IUnsafeCollection return sparseIndex; } + /// + /// Removes the value at the specified sparse index. + /// + /// The sparse index of the value to remove. + /// The generation number associated with the sparse index to validate. + /// When this method returns, contains the item that was removed if the removal was successful; otherwise, the default value for type . + /// True if the value was removed, false if the sparse index was not found. + public bool Remove(int sparseIndex, int generation, out T item) + { + item = default; + if (!Contains(sparseIndex, generation)) + { + return false; + } + + var denseIndex = _sparse[sparseIndex]; + var lastIndex = _count - 1; + + if (denseIndex != lastIndex) + { + // Move the last element to the position of the removed element + var lastValue = _dense[lastIndex]; + var lastSparseIndex = _reverse[lastIndex]; // Get sparse index of last element + + _dense[denseIndex] = lastValue; + _reverse[denseIndex] = lastSparseIndex; + + // Update the sparse mapping for the moved element + _sparse[lastSparseIndex] = denseIndex; + } + + // Mark the sparse index as unused and add to free list + _sparse[sparseIndex] = -1; + _generations[sparseIndex]++; // Increment generation to invalidate old references + + item = _dense[denseIndex]; + + _freeSparse.Push(sparseIndex); + _count--; + + return true; + } + /// /// Removes the value at the specified sparse index. /// diff --git a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/MemoryLeakException.cs b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/MemoryLeakException.cs index a07ec28..5dfd62b 100644 --- a/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/MemoryLeakException.cs +++ b/Misaki.HighPerformance.LowLevel/contentFiles/cs/any/MemoryLeakException.cs @@ -1,5 +1,6 @@ using Misaki.HighPerformance.LowLevel.Buffer; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Text; namespace Misaki.HighPerformance.LowLevel; @@ -45,9 +46,11 @@ public class MemoryLeakException : Exception for (var i = 0; i < stackTrace.FrameCount; i++) { var frame = stackTrace.GetFrame(i); - if (frame != null) + var fileName = frame?.GetFileName(); + + if (frame != null && fileName != null) { - stringBuilder.AppendLine($"File: {frame.GetFileName()}, Method: {DiagnosticMethodInfo.Create(frame)?.Name}, Line: {frame.GetFileLineNumber()}"); + stringBuilder.AppendLine($"File: {fileName}, Method: {DiagnosticMethodInfo.Create(frame)?.Name}, Line: {frame.GetFileLineNumber()}"); } } diff --git a/Misaki.HighPerformance.Mathematics.SPMD/IJobSPMD.cs b/Misaki.HighPerformance.Mathematics.SPMD/IJobSPMD.cs index 5be7f99..1527122 100644 --- a/Misaki.HighPerformance.Mathematics.SPMD/IJobSPMD.cs +++ b/Misaki.HighPerformance.Mathematics.SPMD/IJobSPMD.cs @@ -34,27 +34,6 @@ internal struct SPMDJobWrapper : IJobParallelFor } } } - - //public void Execute(int startIndex, int endIndex, int threadIndex) - //{ - // for (int i = startIndex; i < endIndex; i++) - // { - // var baseIndex = i * WideLane.LaneWidth; - // var remaining = totalCount - baseIndex; - - // if (remaining >= WideLane.LaneWidth) - // { - // innerJob.Execute>(baseIndex, threadIndex); - // } - // else - // { - // for (var j = 0; j < remaining; j++) - // { - // innerJob.Execute>(baseIndex + j, threadIndex); - // } - // } - // } - //} } internal struct SPMDScalerJobWrapper : IJobParallelFor @@ -68,15 +47,6 @@ internal struct SPMDScalerJobWrapper : IJobParallelFor { innerJob.Execute>(loopIndex, threadIndex); } - - //[MethodImpl(MethodImplOptions.AggressiveInlining)] - //public void Execute(int startIndex, int endIndex, int threadIndex) - //{ - // for (int i = startIndex; i < endIndex; i++) - // { - // innerJob.Execute>(i, threadIndex); - // } - //} } public static class IJobParallelForSPMDExtensions