feat(queue): improve Resize logic and add unit tests

Refactored UnsafeQueue<T>.Resize to prevent shrinking below
current count and handle wrap-around copying correctly.
Exposed AllocationHandle in UnsafeArray<T> via a new property.
Bumped project version to 1.6.10.
Added TestUnsafeQueue class to cover core queue operations.
This commit is contained in:
2026-04-03 15:43:31 +09:00
parent 7d621ae6b3
commit a95381e16d
4 changed files with 114 additions and 5 deletions

View File

@@ -81,6 +81,8 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
#endif #endif
private AllocationHandle _allocationHandle; private AllocationHandle _allocationHandle;
internal readonly AllocationHandle AllocationHandle => _allocationHandle;
public readonly int Count => _count; public readonly int Count => _count;
public readonly int Length => _count; public readonly int Length => _count;

View File

@@ -183,12 +183,39 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
public void Resize(int newSize, AllocationOption option = AllocationOption.None) public void Resize(int newSize, AllocationOption option = AllocationOption.None)
{ {
_array.Resize(newSize, option); if (newSize < _count)
if (_count > newSize)
{ {
_count = newSize; newSize = _count;
} }
var newArray = new UnsafeArray<T>(newSize, _array.AllocationHandle, option);
if (_count > 0)
{
if (_offset + _count <= Capacity)
{
// No wrap-around, single copy
var sizeToCopy = (uint)(_count * sizeof(T));
MemCpy(newArray.GetUnsafePtr(), (byte*)_array.GetUnsafePtr() + _offset * sizeof(T), sizeToCopy);
}
else
{
// Wrap-around, two copies required
var firstPartElements = Capacity - _offset;
var secondPartElements = _count - firstPartElements;
// Copy from _offset to the end of the old array
MemCpy(newArray.GetUnsafePtr(), (byte*)_array.GetUnsafePtr() + _offset * sizeof(T), (uint)(firstPartElements * sizeof(T)));
// Copy from the start of the old array to the remaining count
MemCpy((byte*)newArray.GetUnsafePtr() + firstPartElements * sizeof(T), _array.GetUnsafePtr(), (uint)(secondPartElements * sizeof(T)));
}
}
_array.Dispose();
_array = newArray;
_offset = 0;
} }
public void Clear() public void Clear()

View File

@@ -7,7 +7,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Misaki</Authors> <Authors>Misaki</Authors>
<AssemblyVersion>1.6.9</AssemblyVersion> <AssemblyVersion>1.6.10</AssemblyVersion>
<Version>$(AssemblyVersion)</Version> <Version>$(AssemblyVersion)</Version>
<PackageProjectUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</PackageProjectUrl> <PackageProjectUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</PackageProjectUrl>
<RepositoryUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</RepositoryUrl> <RepositoryUrl>https://git.personalnas.com/Misaki/Misaki.HighPerformance.git</RepositoryUrl>

View File

@@ -0,0 +1,80 @@
using Misaki.HighPerformance.LowLevel.Collections;
using System;
using System.Collections.Generic;
using System.Text;
namespace Misaki.HighPerformance.Test.UnitTest.Collections;
[TestClass]
public class TestUnsafeQueue
{
private UnsafeQueue<int> _queue;
[TestInitialize]
public void Setup()
{
_queue = new UnsafeQueue<int>(4, LowLevel.Buffer.Allocator.Persistent);
}
[TestCleanup]
public void Cleanup()
{
_queue.Dispose();
}
[TestMethod]
public void TestEnqueueDequeue()
{
_queue.Enqueue(1);
_queue.Enqueue(2);
_queue.Enqueue(3);
Assert.AreEqual(3, _queue.Count);
Assert.AreEqual(1, _queue.Dequeue());
Assert.AreEqual(2, _queue.Dequeue());
Assert.AreEqual(3, _queue.Dequeue());
Assert.AreEqual(0, _queue.Count);
}
[TestMethod]
public void TestPeek()
{
_queue.Enqueue(10);
_queue.Enqueue(20);
Assert.AreEqual(10, _queue.Peek());
Assert.AreEqual(10, _queue.Dequeue());
Assert.AreEqual(20, _queue.Peek());
}
[TestMethod]
public void TestTryPeek()
{
Assert.IsFalse(_queue.TryPeek(out _));
_queue.Enqueue(5);
Assert.IsTrue(_queue.TryPeek(out int value));
Assert.AreEqual(5, value);
}
[TestMethod]
public void TestResize()
{
for (int i = 0; i < 10; i++)
{
_queue.Enqueue(i);
}
Assert.AreEqual(10, _queue.Count);
_queue.Dequeue();
_queue.Dequeue();
for (int i = 10; i < 20; i++)
{
_queue.Enqueue(i);
}
for (int i = 2; i < 20; i++)
{
Assert.AreEqual(i, _queue.Dequeue());
}
}
}