feat(memory): transition to AllocationHandle API

Replaced the deprecated Allocator API with the new AllocationHandle API across the codebase. Updated constructors, methods, and tests to use AllocationHandle for memory management. Marked Allocator-based methods as [Obsolete] and provided alternatives.

Added OwnershipTransferAnalyzer to detect ownership transfer issues and introduced OwnershipTransferAttribute for marking parameters. Enhanced DefensiveCopyAnalyzer with additional checks for readonly and ValueType instances.

Refactored internal memory management in AllocationManager and updated benchmarks, utilities, and documentation to reflect the changes.

BREAKING CHANGE: Deprecated Allocator API in favor of AllocationHandle. Updated constructors and methods to use AllocationHandle. Users must migrate to the new API.
This commit is contained in:
2026-04-12 17:50:12 +09:00
parent a0deadc363
commit 9c4faa107a
40 changed files with 260 additions and 85 deletions

View File

@@ -5,7 +5,7 @@
<IncludeBuildOutput>False</IncludeBuildOutput> <IncludeBuildOutput>False</IncludeBuildOutput>
<SuppressDependenciesWhenPacking>True</SuppressDependenciesWhenPacking> <SuppressDependenciesWhenPacking>True</SuppressDependenciesWhenPacking>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild> <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<AssemblyVersion>1.1.0</AssemblyVersion> <AssemblyVersion>1.1.1</AssemblyVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@@ -34,15 +34,25 @@ namespace Misaki.HighPerformance.Analyzer
// 1. Basic Filters: Must be an instance method on a Value Type (Struct) // 1. Basic Filters: Must be an instance method on a Value Type (Struct)
if (method.IsStatic || instance == null) if (method.IsStatic || instance == null)
{
return; return;
}
if (!instance.Type.IsValueType) if (!instance.Type.IsValueType)
{
return; // Classes don't copy return; // Classes don't copy
}
if (instance.Type.IsReadOnly) if (instance.Type.IsReadOnly)
{
return; // Readonly structs are safe (compiler enforced) return; // Readonly structs are safe (compiler enforced)
}
// 2. If the method itself is 'readonly', it promises not to mutate, so no copy needed. // 2. If the method itself is 'readonly', it promises not to mutate, so no copy needed.
if (method.IsReadOnly) if (method.IsReadOnly)
{
return; return;
}
// 3. CHECK THE CONTEXT: Is the variable we are calling on "Read Only"? // 3. CHECK THE CONTEXT: Is the variable we are calling on "Read Only"?
if (IsReadOnlyContext(instance, out var variableName)) if (IsReadOnlyContext(instance, out var variableName))

View File

@@ -0,0 +1,117 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace Misaki.HighPerformance.Analyzer
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class OwnershipTransferAnalyzer : DiagnosticAnalyzer
{
public const string DIAGNOSTIC_ID = "MHP003";
private static readonly DiagnosticDescriptor s_rule = new DiagnosticDescriptor(
DIAGNOSTIC_ID,
"Ownership transfer detected",
"Variable '{0}' is used after its ownership has been transferred.",
"Safety",
DiagnosticSeverity.Error,
isEnabledByDefault: true);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_rule);
public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
// Register an action to intercept method and function calls
context.RegisterSyntaxNodeAction(AnalyzeInvocation, SyntaxKind.InvocationExpression);
}
private void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var semanticModel = context.SemanticModel;
var symbolInfo = semanticModel.GetSymbolInfo(invocation);
if (!(symbolInfo.Symbol is IMethodSymbol methodSymbol))
{
return;
}
for (var i = 0; i < invocation.ArgumentList.Arguments.Count; i++)
{
var argument = invocation.ArgumentList.Arguments[i];
IParameterSymbol parameter = null;
// Handle named arguments if present
if (argument.NameColon != null)
{
parameter = methodSymbol.Parameters.FirstOrDefault(p => p.Name == argument.NameColon.Name.Identifier.ValueText);
}
else if (i < methodSymbol.Parameters.Length)
{
parameter = methodSymbol.Parameters[i];
// Handle params arrays
if (parameter.IsParams && i >= methodSymbol.Parameters.Length - 1)
{
parameter = methodSymbol.Parameters[methodSymbol.Parameters.Length - 1];
}
}
if (parameter == null)
{
continue;
}
// Check if the parameter requires an ownership transfer
var hasOwnershipAttribute = parameter.GetAttributes()
.Any(attr => attr.AttributeClass?.Name == "OwnershipTransferAttribute" || attr.AttributeClass?.Name == "OwnershipTransfer");
if (hasOwnershipAttribute)
{
var argSymbolInfo = semanticModel.GetSymbolInfo(argument.Expression);
var transferredSymbol = argSymbolInfo.Symbol;
// Only track local variables and parameters as they represent single runtime instances within the scope
if (transferredSymbol is ILocalSymbol || transferredSymbol is IParameterSymbol)
{
CheckForSubsequentUsage(context, invocation, transferredSymbol);
}
}
}
}
private void CheckForSubsequentUsage(SyntaxNodeAnalysisContext context, InvocationExpressionSyntax invocation, ISymbol transferredSymbol)
{
// Find the lexical block to scan for subsequent accesses (supports standard methods and top-level statements)
var block = invocation.Ancestors().OfType<BlockSyntax>().FirstOrDefault()
?? (SyntaxNode)invocation.Ancestors().OfType<CompilationUnitSyntax>().FirstOrDefault();
if (block == null)
{
return;
}
// Find all identifiers inside this method implementation
var identifiers = block.DescendantNodes().OfType<IdentifierNameSyntax>();
foreach (var identifier in identifiers)
{
// Trigger a warning if the code accesses the data textually after the invocation ends
if (identifier.SpanStart > invocation.Span.End)
{
var symbol = context.SemanticModel.GetSymbolInfo(identifier).Symbol;
if (symbol != null && symbol.Equals(transferredSymbol, SymbolEqualityComparer.Default))
{
var diagnostic = Diagnostic.Create(s_rule, identifier.GetLocation(), transferredSymbol.Name);
context.ReportDiagnostic(diagnostic);
}
}
}
}
}
}

View File

@@ -4,3 +4,8 @@ namespace Misaki.HighPerformance.LowLevel;
public class NonCopyableAttribute : Attribute public class NonCopyableAttribute : Attribute
{ {
} }
[AttributeUsage(AttributeTargets.Parameter)]
public class OwnershipTransferAttribute : Attribute
{
}

View File

@@ -3,6 +3,7 @@ using Misaki.HighPerformance.Collections;
#endif #endif
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
namespace Misaki.HighPerformance.LowLevel.Buffer; namespace Misaki.HighPerformance.LowLevel.Buffer;
@@ -81,7 +82,7 @@ public readonly struct AllocationManagerInitOpts
/// </summary> /// </summary>
public static unsafe class AllocationManager public static unsafe class AllocationManager
{ {
private struct HeapAllocator : IAllocator internal struct HeapAllocator : IAllocator
{ {
private AllocationHandle _handle; private AllocationHandle _handle;
@@ -145,13 +146,13 @@ public static unsafe class AllocationManager
#endif #endif
} }
private static MemoryPool<VirtualArena, VirtualArena.CreationOptions> s_arenaAllocator; internal static MemoryPool<VirtualArena, VirtualArena.CreationOptions> s_arenaAllocator;
private static MemoryPool<FreeList, FreeList.CreationOptions> s_freeListAllocator; internal static MemoryPool<FreeList, FreeList.CreationOptions> s_freeListAllocator;
internal static HeapAllocator* s_pHeapAllocator;
[ThreadStatic] [ThreadStatic]
private static MemoryPool<VirtualStack, VirtualStack.CreationOptions> t_stackAllocator; private static MemoryPool<VirtualStack, VirtualStack.CreationOptions> t_stackAllocator;
private static HeapAllocator* s_pHeapAllocator;
#if MHP_ENABLE_SAFETY_CHECKS #if MHP_ENABLE_SAFETY_CHECKS
private static ConcurrentSlotMap<AllocationInfo> s_allocations = null!; private static ConcurrentSlotMap<AllocationInfo> s_allocations = null!;
@@ -256,6 +257,7 @@ public static unsafe class AllocationManager
/// <returns>A reference to the allocation pHandle associated with the specified allocator type.</returns> /// <returns>A reference to the allocation pHandle associated with the specified allocator type.</returns>
/// <exception cref="ArgumentException"></exception> /// <exception cref="ArgumentException"></exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
[Obsolete("Use AllocationHandle instead.")]
public static AllocationHandle GetAllocationHandle(Allocator allocator) public static AllocationHandle GetAllocationHandle(Allocator allocator)
{ {
Debug.Assert(s_initialized, "AllocationManager is not initialized."); Debug.Assert(s_initialized, "AllocationManager is not initialized.");

View File

@@ -1,3 +1,5 @@
using System.Runtime.Versioning;
namespace Misaki.HighPerformance.LowLevel.Buffer; namespace Misaki.HighPerformance.LowLevel.Buffer;
[Flags] [Flags]
@@ -13,6 +15,7 @@ public enum AllocationOption : byte
Clear = 1 << 0 Clear = 1 << 0
} }
[Obsolete("Use AllocationHandle instead.")]
public enum Allocator : byte public enum Allocator : byte
{ {
// Make the first allocator as invalid because we don't want to user create a default collection without passing any parameters // Make the first allocator as invalid because we don't want to user create a default collection without passing any parameters

View File

@@ -76,6 +76,26 @@ public readonly struct MemoryHandle : IDisposable, IEquatable<MemoryHandle>
/// </summary> /// </summary>
public readonly unsafe struct AllocationHandle public readonly unsafe struct AllocationHandle
{ {
/// <summary>
/// The invalid allocator. This value is reserved and should not be used for actual memory allocations. It can be used to indicate an uninitialized or invalid state in allocation scenarios.
/// </summary>
public static readonly AllocationHandle Invalid = default;
/// <summary>
/// Allocator for temporary allocations. Allocations are automatically released after use automatically.
/// </summary>
public static readonly AllocationHandle Temp = AllocationManager.s_arenaAllocator.AllocationHandle;
/// <summary>
/// Allocator for persistent allocations. Allocations are not automatically released after use.
/// </summary>
public static readonly AllocationHandle FreeList = AllocationManager.s_freeListAllocator.AllocationHandle;
/// <summary>
/// Allocator for persistent allocations using a free list. Allocations are not automatically released after use, but can be reused to reduce fragmentation, system call and improve performance.
/// </summary>
public static readonly AllocationHandle Persistent = AllocationManager.s_pHeapAllocator->Handle;
/// <summary> /// <summary>
/// Gets a pointer to the state instance associated with this allocation handle. /// Gets a pointer to the state instance associated with this allocation handle.
/// </summary> /// </summary>

View File

@@ -36,7 +36,7 @@ public unsafe struct MemoryBlock : IDisposable
} }
public MemoryBlock() public MemoryBlock()
: this(0, 0, Allocator.Invalid) : this(1, 8, AllocationHandle.Invalid)
{ {
} }
@@ -66,6 +66,7 @@ public unsafe struct MemoryBlock : IDisposable
/// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param> /// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param>
/// <param name="allocationOption">Determines how the memory should be allocated.</param> /// <param name="allocationOption">Determines how the memory should be allocated.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the specified number of elements is less than or equal to zero.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the specified number of elements is less than or equal to zero.</exception>
[Obsolete("Use AllocationHandle instead.")]
public MemoryBlock(nuint size, nuint alignment, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public MemoryBlock(nuint size, nuint alignment, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(size, alignment, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(size, alignment, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

View File

@@ -620,7 +620,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
return MoveNextSearch(ref bucketIndex, ref nextIndex, out index); return MoveNextSearch(ref bucketIndex, ref nextIndex, out index);
} }
internal UnsafeArray<TKey> GetKeyArray(Allocator allocator) internal UnsafeArray<TKey> GetKeyArray(AllocationHandle allocator)
{ {
ThrowIfNotCreated(); ThrowIfNotCreated();
@@ -640,7 +640,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
return result; return result;
} }
internal UnsafeArray<TValue> GetValueArray<TValue>(Allocator allocator) internal UnsafeArray<TValue> GetValueArray<TValue>(AllocationHandle allocator)
where TValue : unmanaged where TValue : unmanaged
{ {
ThrowIfNotCreated(); ThrowIfNotCreated();
@@ -661,7 +661,7 @@ public unsafe struct HashMapHelper<TKey> : IDisposable
return result; return result;
} }
public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays<TValue>(Allocator allocator) public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays<TValue>(AllocationHandle allocator)
where TValue : unmanaged where TValue : unmanaged
{ {
ThrowIfNotCreated(); ThrowIfNotCreated();

View File

@@ -1,7 +1,6 @@
using Misaki.HighPerformance.LowLevel.Buffer; using Misaki.HighPerformance.LowLevel.Buffer;
using Misaki.HighPerformance.LowLevel.Collections.Contracts; using Misaki.HighPerformance.LowLevel.Collections.Contracts;
using Misaki.HighPerformance.LowLevel.Utilities; using Misaki.HighPerformance.LowLevel.Utilities;
using System.Collections;
using System.Diagnostics; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@@ -119,10 +118,10 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
} }
/// <summary> /// <summary>
/// Invalid constructor, use <see cref="UnsafeArray(int, Allocator, AllocationOption)"/> or <see cref="UnsafeArray(int, AllocationHandle, AllocationOption)"/> instead. /// Initializes a new instance of UnsafeArray with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeArray() public UnsafeArray()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -157,6 +156,7 @@ public unsafe struct UnsafeArray<T> : IUnsafeCollection<T>
/// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param> /// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param>
/// <param name="allocationOption">Determines how the memory should be allocated.</param> /// <param name="allocationOption">Determines how the memory should be allocated.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the specified number of elements is less than or equal to zero.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the specified number of elements is less than or equal to zero.</exception>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeArray(int count, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeArray(int count, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(count, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(count, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

View File

@@ -82,11 +82,11 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
public readonly bool IsCreated => _bits.IsCreated; public readonly bool IsCreated => _bits.IsCreated;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UnsafeBitSet" /> class. /// Initializes a new instance of UnsafeBitSet with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeBitSet() public UnsafeBitSet()
{ {
_bits = new UnsafeArray<uint>(0, Allocator.Invalid, AllocationOption.None); _bits = new UnsafeArray<uint>(1, AllocationHandle.Persistent, AllocationOption.None);
} }
/// <summary> /// <summary>
@@ -106,6 +106,7 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UnsafeBitSet" /> class. /// Initializes a new instance of the <see cref="UnsafeBitSet" /> class.
/// </summary> /// </summary>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeBitSet(int minimalLength, Allocator allocator, AllocationOption option = AllocationOption.None) public UnsafeBitSet(int minimalLength, Allocator allocator, AllocationOption option = AllocationOption.None)
: this(minimalLength, AllocationManager.GetAllocationHandle(allocator), option) : this(minimalLength, AllocationManager.GetAllocationHandle(allocator), option)
{ {
@@ -114,6 +115,7 @@ public unsafe struct UnsafeBitSet : IDisposable, IEquatable<UnsafeBitSet>
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="UnsafeBitSet" /> class. /// Initializes a new instance of the <see cref="UnsafeBitSet" /> class.
/// </summary> /// </summary>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeBitSet(Span<uint> bits, Allocator allocator) public UnsafeBitSet(Span<uint> bits, Allocator allocator)
{ {
_bits = new UnsafeArray<uint>(bits.Length, allocator, AllocationOption.None); _bits = new UnsafeArray<uint>(bits.Length, allocator, AllocationOption.None);

View File

@@ -97,6 +97,7 @@ public unsafe struct UnsafeChunkedQueue<T> : IDisposable
#endif #endif
} }
[Obsolete("Use AllocationHandle instead.")]
public UnsafeChunkedQueue(int capacityPerChunk, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeChunkedQueue(int capacityPerChunk, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacityPerChunk, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacityPerChunk, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

View File

@@ -75,10 +75,10 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
} }
/// <summary> /// <summary>
/// Invalid constructor, use <see cref="UnsafeHashMap(int, Allocator, AllocationOption)"/> or <see cref="UnsafeHashMap(int, AllocationHandle, AllocationOption)"/> instead. /// Initializes a new instance of UnsafeHashMap with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeHashMap() public UnsafeHashMap()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -87,6 +87,7 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
_helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption); _helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption);
} }
[Obsolete("Use AllocationHandle instead.")]
public UnsafeHashMap(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeHashMap(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {
@@ -235,32 +236,34 @@ public unsafe struct UnsafeHashMap<TKey, TValue> : IUnsafeHashCollection<KeyValu
/// <summary> /// <summary>
/// Retrieves an array of keys from the hash map. /// Retrieves an array of keys from the hash map.
/// </summary> /// </summary>
/// <param name="allocationHandle">The allocation handle to use to allocate the array.</param>
/// <returns>An array containing the keys stored in the hash map.</returns> /// <returns>An array containing the keys stored in the hash map.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<TKey> GetKeyArray(Allocator allocator) public UnsafeArray<TKey> GetKeyArray(AllocationHandle allocationHandle)
{ {
return _helper.GetKeyArray(allocator); return _helper.GetKeyArray(allocationHandle);
} }
/// <summary> /// <summary>
/// Retrieves an array of values from the underlying hash map. /// Retrieves an array of values from the underlying hash map.
/// </summary> /// </summary>
/// <param name="allocationHandle">The allocation handle to use to allocate the array.</param>
/// <returns>An UnsafeArray containing the values stored in the hash map.</returns> /// <returns>An UnsafeArray containing the values stored in the hash map.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<TValue> GetValueArray(Allocator allocator) public UnsafeArray<TValue> GetValueArray(AllocationHandle allocationHandle)
{ {
return _helper.GetValueArray<TValue>(allocator); return _helper.GetValueArray<TValue>(allocationHandle);
} }
/// <summary> /// <summary>
/// Retrieves an array of key-value pairs from the hash map. The keys are of type TKey and the values are of type /// Retrieves an array of key-value pairs from the hash map. The keys are of type TKey and the values are of type TValue.
/// TValue.
/// </summary> /// </summary>
/// <param name="allocationHandle">The allocation handle to use to allocate the array.</param>
/// <returns>Returns an UnsafeArray containing KeyValuePair objects.</returns> /// <returns>Returns an UnsafeArray containing KeyValuePair objects.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays(Allocator allocator) public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays(AllocationHandle allocationHandle)
{ {
return _helper.GetKeyValueArrays<TValue>(allocator); return _helper.GetKeyValueArrays<TValue>(allocationHandle);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -43,10 +43,10 @@ public unsafe struct UnsafeHashSet<T> : IUnsafeHashCollection<T>
public readonly bool IsCreated => _helper.IsCreated; public readonly bool IsCreated => _helper.IsCreated;
/// <summary> /// <summary>
/// Invalid constructor. Use <see cref="UnsafeHashSet(int, Allocator, AllocationOption)"/> or <see cref="UnsafeHashSet(int, AllocationHandle, AllocationOption)"/> instead."/> /// Initializes a new instance of UnsafeHashSet with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeHashSet() public UnsafeHashSet()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -55,6 +55,7 @@ public unsafe struct UnsafeHashSet<T> : IUnsafeHashCollection<T>
_helper = new HashMapHelper<T>(capacity, 0, 0, HashMapHelper<T>.MINIMAL_CAPACITY, handle, allocationOption); _helper = new HashMapHelper<T>(capacity, 0, 0, HashMapHelper<T>.MINIMAL_CAPACITY, handle, allocationOption);
} }
[Obsolete("Use AllocationHandle instead.")]
public UnsafeHashSet(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeHashSet(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {
@@ -112,12 +113,12 @@ public unsafe struct UnsafeHashSet<T> : IUnsafeHashCollection<T>
/// <summary> /// <summary>
/// Returns an array with a copy of this set's values (in no particular order). /// Returns an array with a copy of this set's values (in no particular order).
/// </summary> /// </summary>
/// <param name="allocator">The allocator to use.</param> /// <param name="allocationHandle">The allocation handle to use to allocate the array.</param>
/// <returns>An array with a copy of the set's values.</returns> /// <returns>An array with a copy of the set's values.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<T> ToNativeArray(Allocator allocator) public UnsafeArray<T> ToUnsafeArray(AllocationHandle allocationHandle)
{ {
return _helper.GetKeyArray(allocator); return _helper.GetKeyArray(allocationHandle);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -174,7 +174,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
/// Invalid constructor, use <see cref="UnsafeList(int, Allocator, AllocationOption)"/> or <see cref="UnsafeList(int, AllocationHandle, AllocationOption)"/> instead. /// Invalid constructor, use <see cref="UnsafeList(int, Allocator, AllocationOption)"/> or <see cref="UnsafeList(int, AllocationHandle, AllocationOption)"/> instead.
/// </summary> /// </summary>
public UnsafeList() public UnsafeList()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -196,6 +196,7 @@ public unsafe struct UnsafeList<T> : IUnsafeCollection<T>
/// <param name="capacity">Specifies the number of initial capacity to allocate in the list, which must be greater than zero.</param> /// <param name="capacity">Specifies the number of initial capacity to allocate in the list, which must be greater than zero.</param>
/// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param> /// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param>
/// <param name="allocationOption">Determines how the memory should be allocated.</param> /// <param name="allocationOption">Determines how the memory should be allocated.</param>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeList(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeList(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

View File

@@ -112,8 +112,11 @@ public unsafe struct UnsafeMultiHashMap<TKey, TValue> : IUnsafeHashCollection<Ke
public readonly int Capacity => _helper.Capacity; public readonly int Capacity => _helper.Capacity;
public readonly bool IsCreated => _helper.IsCreated; public readonly bool IsCreated => _helper.IsCreated;
/// <summary>
/// Initializes a new instance of UnsafeMultiHashMap with a default size of 1 and a persistent allocation handle.
/// </summary>
public UnsafeMultiHashMap() public UnsafeMultiHashMap()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -122,6 +125,7 @@ public unsafe struct UnsafeMultiHashMap<TKey, TValue> : IUnsafeHashCollection<Ke
_helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption); _helper = new HashMapHelper<TKey>(capacity, sizeof(TValue), (int)AlignOf<TValue>(), HashMapHelper<TKey>.MINIMAL_CAPACITY, handle, allocationOption);
} }
[Obsolete("Use AllocationHandle instead.")]
public UnsafeMultiHashMap(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeMultiHashMap(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {
@@ -239,21 +243,21 @@ public unsafe struct UnsafeMultiHashMap<TKey, TValue> : IUnsafeHashCollection<Ke
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<TKey> GetKeyArray(Allocator allocator) public UnsafeArray<TKey> GetKeyArray(AllocationHandle allocationHandle)
{ {
return _helper.GetKeyArray(allocator); return _helper.GetKeyArray(allocationHandle);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<TValue> GetValueArray(Allocator allocator) public UnsafeArray<TValue> GetValueArray(AllocationHandle allocationHandle)
{ {
return _helper.GetValueArray<TValue>(allocator); return _helper.GetValueArray<TValue>(allocationHandle);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays(Allocator allocator) public UnsafeArray<KeyValuePair<TKey, TValue>> GetKeyValueArrays(AllocationHandle allocationHandle)
{ {
return _helper.GetKeyValueArrays<TValue>(allocator); return _helper.GetKeyValueArrays<TValue>(allocationHandle);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]

View File

@@ -58,10 +58,10 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
} }
/// <summary> /// <summary>
/// Invalid constructor. Use <see cref="UnsafeQueue(int, Allocator, AllocationOption)"/> or <see cref="UnsafeQueue(int, AllocationHandle, AllocationOption)"/> instead."/> /// Initializes a new instance of UnsafeQueue with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeQueue() public UnsafeQueue()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -72,6 +72,7 @@ public unsafe struct UnsafeQueue<T> : IUnsafeCollection<T>
_offset = 0; _offset = 0;
} }
[Obsolete("Use AllocationHandle instead.")]
public UnsafeQueue(int capacity, Allocator allocator, AllocationOption allocationType = AllocationOption.None) public UnsafeQueue(int capacity, Allocator allocator, AllocationOption allocationType = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationType) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationType)
{ {

View File

@@ -82,10 +82,10 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
public readonly bool IsCreated => _data.IsCreated && _generations.IsCreated && _freeSlots.IsCreated && _validBits.IsCreated; public readonly bool IsCreated => _data.IsCreated && _generations.IsCreated && _freeSlots.IsCreated && _validBits.IsCreated;
/// <summary> /// <summary>
/// Invalid constructor. Use <see cref="UnsafeSlotMap(int, Allocator, AllocationOption)"/> or <see cref="UnsafeSlotMap(int, AllocationHandle, AllocationOption)"/> instead."/> /// Initializes a new instance of UnsafeSlotMap with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeSlotMap() public UnsafeSlotMap()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -126,6 +126,7 @@ public unsafe struct UnsafeSlotMap<T> : IUnsafeCollection<T>
/// <param name="capacity">The initial number of slots to allocate for the map. Must be greater than zero.</param> /// <param name="capacity">The initial number of slots to allocate for the map. Must be greater than zero.</param>
/// <param name="allocator">The allocator to use for memory management of the slot map.</param> /// <param name="allocator">The allocator to use for memory management of the slot map.</param>
/// <param name="allocationOption">The allocation option that determines how memory is allocated. The default is AllocationOption.None.</param> /// <param name="allocationOption">The allocation option that determines how memory is allocated. The default is AllocationOption.None.</param>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeSlotMap(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeSlotMap(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

View File

@@ -88,7 +88,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// Constructs an UnsafeSparseSet with a default size of 1 and uses the Persistent allocator. /// Constructs an UnsafeSparseSet with a default size of 1 and uses the Persistent allocator.
/// </summary> /// </summary>
public UnsafeSparseSet() public UnsafeSparseSet()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -133,6 +133,7 @@ public unsafe struct UnsafeSparseSet<T> : IUnsafeCollection<T>
/// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param> /// <param name="allocator">Specifies the allocator to use for memory allocation, which determines the memory management strategy.</param>
/// <param name="allocationOption">Determines how the memory should be allocated.</param> /// <param name="allocationOption">Determines how the memory should be allocated.</param>
/// <exception cref="ArgumentOutOfRangeException">Thrown when the specified capacity is less than or equal to zero.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the specified capacity is less than or equal to zero.</exception>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeSparseSet(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeSparseSet(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

View File

@@ -77,10 +77,10 @@ public unsafe struct UnsafeStack<T> : IUnsafeCollection<T>
public readonly bool IsCreated => _array.IsCreated; public readonly bool IsCreated => _array.IsCreated;
/// <summary> /// <summary>
/// Invalid constructor, use <see cref="UnsafeStack(int, Allocator, AllocationOption)"/> or <see cref="UnsafeStack(int, AllocationHandle, AllocationOption)"/> instead. /// Initializes a new instance of UnsafeStack with a default size of 1 and a persistent allocation handle.
/// </summary> /// </summary>
public UnsafeStack() public UnsafeStack()
: this(0, Allocator.Invalid) : this(1, AllocationHandle.Persistent)
{ {
} }
@@ -102,6 +102,7 @@ public unsafe struct UnsafeStack<T> : IUnsafeCollection<T>
/// <param name="capacity">The initial number of elements that the stack can hold. Must be greater than zero.</param> /// <param name="capacity">The initial number of elements that the stack can hold. Must be greater than zero.</param>
/// <param name="allocator">The allocator to use for memory management of the stack's storage.</param> /// <param name="allocator">The allocator to use for memory management of the stack's storage.</param>
/// <param name="allocationOption">The allocation option that determines how memory is allocated for the stack. The default is AllocationOption.None.</param> /// <param name="allocationOption">The allocation option that determines how memory is allocated for the stack. The default is AllocationOption.None.</param>
[Obsolete("Use AllocationHandle instead.")]
public UnsafeStack(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None) public UnsafeStack(int capacity, Allocator allocator, AllocationOption allocationOption = AllocationOption.None)
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption) : this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
{ {

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.12</AssemblyVersion> <AssemblyVersion>1.6.13</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

@@ -43,12 +43,12 @@ public static unsafe class UnsafeCollectionUtility
/// </summary> /// </summary>
/// <typeparam name="T">The type of elements in the array, which must be unmanaged.</typeparam> /// <typeparam name="T">The type of elements in the array, which must be unmanaged.</typeparam>
/// <param name="source">The managed array to convert.</param> /// <param name="source">The managed array to convert.</param>
/// <param name="allocator">The allocator to use for memory allocation of the UnsafeArray.</param> /// <param name="allocationHandle">The allocation handle to use for memory allocation of the UnsafeArray.</param>
/// <returns>A new UnsafeArray containing a copy of the source array elements.</returns> /// <returns>A new UnsafeArray containing a copy of the source array elements.</returns>
public static UnsafeArray<T> ToUnsafeArray<T>(this T[] source, Allocator allocator) public static UnsafeArray<T> ToUnsafeArray<T>(this T[] source, AllocationHandle allocationHandle)
where T : unmanaged where T : unmanaged
{ {
var array = new UnsafeArray<T>(source.Length, allocator); var array = new UnsafeArray<T>(source.Length, allocationHandle);
fixed (T* pSrc = source) fixed (T* pSrc = source)
{ {
MemCpy(array.GetUnsafePtr(), pSrc, (uint)(source.Length * sizeof(T))); MemCpy(array.GetUnsafePtr(), pSrc, (uint)(source.Length * sizeof(T)));
@@ -62,12 +62,12 @@ public static unsafe class UnsafeCollectionUtility
/// </summary> /// </summary>
/// <typeparam name="T">The type of elements in the list, which must be unmanaged.</typeparam> /// <typeparam name="T">The type of elements in the list, which must be unmanaged.</typeparam>
/// <param name="source">The managed List to convert.</param> /// <param name="source">The managed List to convert.</param>
/// <param name="allocator">The allocator to use for memory allocation of the UnsafeList.</param> /// <param name="allocationHandle">The allocation handle to use for memory allocation of the UnsafeList.</param>
/// <returns>A new UnsafeList containing a copy of the source list elements.</returns> /// <returns>A new UnsafeList containing a copy of the source list elements.</returns>
public static UnsafeList<T> ToUnsafeList<T>(this List<T> source, Allocator allocator) public static UnsafeList<T> ToUnsafeList<T>(this List<T> source, AllocationHandle allocationHandle)
where T : unmanaged where T : unmanaged
{ {
var list = new UnsafeList<T>(source.Count, allocator); var list = new UnsafeList<T>(source.Count, allocationHandle);
fixed (T* pSrc = CollectionsMarshal.AsSpan(source)) fixed (T* pSrc = CollectionsMarshal.AsSpan(source))
{ {
MemCpy(list.GetUnsafePtr(), pSrc, (uint)(source.Count * sizeof(T))); MemCpy(list.GetUnsafePtr(), pSrc, (uint)(source.Count * sizeof(T)));

View File

@@ -15,7 +15,7 @@ public class CollectionBenchmark
[GlobalSetup] [GlobalSetup]
public void Setup() public void Setup()
{ {
_array = new UnsafeArray<Vector256<int>>(count, Allocator.Persistent); _array = new UnsafeArray<Vector256<int>>(count, AllocationHandle.Persistent);
} }
[GlobalCleanup] [GlobalCleanup]

View File

@@ -1,4 +1,4 @@
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Attributes;
using Misaki.HighPerformance.LowLevel.Collections; using Misaki.HighPerformance.LowLevel.Collections;
namespace Misaki.HighPerformance.Test.Benchmark; namespace Misaki.HighPerformance.Test.Benchmark;
@@ -14,7 +14,7 @@ public class HashMapBenchmark
[IterationSetup] [IterationSetup]
public void Setup() public void Setup()
{ {
//_unsafeHashMap = new UnsafeHashMap<int, float>(count, Allocator.Persistent); //_unsafeHashMap = new UnsafeHashMap<int, float>(count, AllocationHandle.Persistent);
_dictionary = new Dictionary<int, float>(count); _dictionary = new Dictionary<int, float>(count);
for (var i = 0; i < count; i++) for (var i = 0; i < count; i++)

View File

@@ -21,7 +21,7 @@ public class ParallelNoiseBenchmark
public void Setup() public void Setup()
{ {
_jobScheduler = new JobScheduler(Environment.ProcessorCount); _jobScheduler = new JobScheduler(Environment.ProcessorCount);
_buffers = new UnsafeArray<float>(_LENGTH, Allocator.Persistent); _buffers = new UnsafeArray<float>(_LENGTH, AllocationHandle.Persistent);
} }
[GlobalCleanup] [GlobalCleanup]

View File

@@ -3,10 +3,10 @@ using Misaki.HighPerformance.LowLevel.Collections;
//BenchmarkRunner.Run<SPMDBenchmark>(); //BenchmarkRunner.Run<SPMDBenchmark>();
//AllocationManager.Initialize(AllocationManagerInitOpts.Default); AllocationManager.Initialize(AllocationManagerInitOpts.Default);
//var set = new UnsafeBitSet(100, Allocator.Persistent, AllocationOption.Clear); var set = new UnsafeBitSet(100, AllocationHandle.Persistent, AllocationOption.Clear);
//set.SetBit(0); set.SetBit(0);
//Console.WriteLine(set.NextSetBit(0)); Console.WriteLine(set.NextSetBit(0));
//set.Dispose(); set.Dispose();
//AllocationManager.Dispose(); AllocationManager.Dispose();

View File

@@ -9,8 +9,8 @@ public class TestAllocationManager
[TestMethod] [TestMethod]
public void PersistentAllocationTest() public void PersistentAllocationTest()
{ {
var ptr1 = new MemoryBlock(1024, 8, Allocator.Persistent); var ptr1 = new MemoryBlock(1024, 8, AllocationHandle.Persistent);
var ptr2 = new MemoryBlock(2048, 8, Allocator.Persistent); var ptr2 = new MemoryBlock(2048, 8, AllocationHandle.Persistent);
Assert.IsTrue(ptr1.IsCreated); Assert.IsTrue(ptr1.IsCreated);
Assert.IsTrue(ptr2.IsCreated); Assert.IsTrue(ptr2.IsCreated);
@@ -25,8 +25,8 @@ public class TestAllocationManager
[TestMethod] [TestMethod]
public void TempAllocationTest() public void TempAllocationTest()
{ {
var ptr1 = new MemoryBlock(1024, 8, Allocator.Temp); var ptr1 = new MemoryBlock(1024, 8, AllocationHandle.Temp);
var ptr2 = new MemoryBlock(2048, 8, Allocator.Temp); var ptr2 = new MemoryBlock(2048, 8, AllocationHandle.Temp);
Assert.IsTrue(ptr1.IsCreated); Assert.IsTrue(ptr1.IsCreated);
Assert.IsTrue(ptr2.IsCreated); Assert.IsTrue(ptr2.IsCreated);
@@ -41,8 +41,8 @@ public class TestAllocationManager
[TestMethod] [TestMethod]
public void FreeListAllocationTest() public void FreeListAllocationTest()
{ {
var ptr1 = new MemoryBlock(1024, 8, Allocator.FreeList); var ptr1 = new MemoryBlock(1024, 8, AllocationHandle.FreeList);
var ptr2 = new MemoryBlock(2048, 8, Allocator.FreeList); var ptr2 = new MemoryBlock(2048, 8, AllocationHandle.FreeList);
Assert.IsTrue(ptr1.IsCreated); Assert.IsTrue(ptr1.IsCreated);
Assert.IsTrue(ptr2.IsCreated); Assert.IsTrue(ptr2.IsCreated);

View File

@@ -11,7 +11,7 @@ public class TestUnsafeArray
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_arr = new UnsafeArray<int>(16, Allocator.Persistent); _arr = new UnsafeArray<int>(16, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -12,8 +12,8 @@ public class TestUnsafeBitSet
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_set1 = new UnsafeBitSet(16, Allocator.Persistent, AllocationOption.Clear); _set1 = new UnsafeBitSet(16, AllocationHandle.Persistent, AllocationOption.Clear);
_set2 = new UnsafeBitSet(16, Allocator.Persistent, AllocationOption.Clear); _set2 = new UnsafeBitSet(16, AllocationHandle.Persistent, AllocationOption.Clear);
} }
[TestCleanup] [TestCleanup]

View File

@@ -15,7 +15,7 @@ public class TestUnsafeChunkedQueue
[TestMethod] [TestMethod]
public void BasicEnqueueDequeueTest() public void BasicEnqueueDequeueTest()
{ {
using var queue = new UnsafeChunkedQueue<int>(32, Allocator.Persistent); using var queue = new UnsafeChunkedQueue<int>(32, AllocationHandle.Persistent);
Assert.IsTrue(queue.IsCreated); Assert.IsTrue(queue.IsCreated);
@@ -35,7 +35,7 @@ public class TestUnsafeChunkedQueue
public void ChunkExpansionTest() public void ChunkExpansionTest()
{ {
// Force chunk expansions by enqueuing more than the chunk capacity // Force chunk expansions by enqueuing more than the chunk capacity
using var queue = new UnsafeChunkedQueue<int>(16, Allocator.Persistent); using var queue = new UnsafeChunkedQueue<int>(16, AllocationHandle.Persistent);
var totalItems = 100; var totalItems = 100;
@@ -57,7 +57,7 @@ public class TestUnsafeChunkedQueue
public void ConcurrentEnqueueDequeueTest() public void ConcurrentEnqueueDequeueTest()
{ {
// Multi-threaded stress test to verify lock-free safety and chunk caching // Multi-threaded stress test to verify lock-free safety and chunk caching
using var queue = new UnsafeChunkedQueue<int>(64, Allocator.Persistent); using var queue = new UnsafeChunkedQueue<int>(64, AllocationHandle.Persistent);
var totalElements = 100_000; var totalElements = 100_000;
var enqueueTask = Task.Run(() => var enqueueTask = Task.Run(() =>

View File

@@ -11,7 +11,7 @@ public class TestUnsafeHashMap
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_map = new UnsafeHashMap<int, int>(4, Allocator.Persistent); _map = new UnsafeHashMap<int, int>(4, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -11,7 +11,7 @@ public class TestUnsafeHashSet
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_set = new UnsafeHashSet<int>(4, Allocator.Persistent); _set = new UnsafeHashSet<int>(4, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -11,7 +11,7 @@ public class TestUnsafeList
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_list = new UnsafeList<int>(4, Allocator.Persistent); _list = new UnsafeList<int>(4, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -11,7 +11,7 @@ public class TestUnsafeMultiHashMap
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_multiHashMap = new UnsafeMultiHashMap<int, int>(4, Allocator.Persistent); _multiHashMap = new UnsafeMultiHashMap<int, int>(4, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -10,7 +10,7 @@ public class TestUnsafeQueue
[TestInitialize] [TestInitialize]
public void Setup() public void Setup()
{ {
_queue = new UnsafeQueue<int>(4, LowLevel.Buffer.Allocator.Persistent); _queue = new UnsafeQueue<int>(4, LowLevel.Buffer.AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -11,7 +11,7 @@ public class TestUnsafeSlotMap
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_slotMap = new UnsafeSlotMap<int>(16, Allocator.Persistent); _slotMap = new UnsafeSlotMap<int>(16, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -11,7 +11,7 @@ public class TestUnsafeSparseSet
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_sparseSet = new UnsafeSparseSet<int>(16, Allocator.Persistent); _sparseSet = new UnsafeSparseSet<int>(16, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -11,7 +11,7 @@ public class TestUnsafeStack
[TestInitialize] [TestInitialize]
public void Initialize() public void Initialize()
{ {
_stack = new UnsafeStack<int>(16, Allocator.Persistent); _stack = new UnsafeStack<int>(16, AllocationHandle.Persistent);
} }
[TestCleanup] [TestCleanup]

View File

@@ -171,7 +171,7 @@ public unsafe class TestJobSystem
{ {
const int arraySize = 10000; const int arraySize = 10000;
using var array = new UnsafeArray<float>(arraySize, Allocator.Persistent); using var array = new UnsafeArray<float>(arraySize, AllocationHandle.Persistent);
for (var i = 0; i < arraySize; i++) for (var i = 0; i < arraySize; i++)
{ {
@@ -296,17 +296,17 @@ public unsafe class TestJobSystem
[TestMethod] [TestMethod]
public void DynamicDispatch() public void DynamicDispatch()
{ {
using var arr = new UnsafeArray<UnsafeArray<int>>(256, Allocator.Persistent); using var arr = new UnsafeArray<UnsafeArray<int>>(256, AllocationHandle.Persistent);
for (var i = 0; i < arr.Length; i++) for (var i = 0; i < arr.Length; i++)
{ {
arr[i] = new UnsafeArray<int>(256, Allocator.Persistent); arr[i] = new UnsafeArray<int>(256, AllocationHandle.Persistent);
for (var j = 0; j < arr[i].Length; j++) for (var j = 0; j < arr[i].Length; j++)
{ {
arr[i][j] = j; arr[i][j] = j;
} }
} }
using var handles = new UnsafeList<JobHandle>(arr.Length, Allocator.Persistent); using var handles = new UnsafeList<JobHandle>(arr.Length, AllocationHandle.Persistent);
var job = new JobDispatchingJob var job = new JobDispatchingJob
{ {

View File

@@ -1,3 +1,4 @@
using Misaki.HighPerformance.LowLevel;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;