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.
147 lines
4.5 KiB
C#
147 lines
4.5 KiB
C#
using Misaki.HighPerformance.LowLevel.Buffer;
|
|
using Misaki.HighPerformance.LowLevel.Collections.Contracts;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace Misaki.HighPerformance.LowLevel.Collections;
|
|
|
|
/// <summary>
|
|
/// A collection that provides fast, unsafe operations for managing a set of unmanaged types. It supports adding,
|
|
/// removing, and checking for values.
|
|
/// </summary>
|
|
/// <typeparam name="T">Represents an unmanaged type that can be compared for equality.</typeparam>
|
|
public unsafe struct UnsafeHashSet<T> : IUnsafeHashCollection<T>
|
|
where T : unmanaged, IEquatable<T>
|
|
{
|
|
public ref struct Enumerator
|
|
{
|
|
internal HashMapHelper<T>.Enumerator _enumerator;
|
|
|
|
public readonly T Current => _enumerator.helper._keys[_enumerator.index];
|
|
|
|
public Enumerator(ref HashMapHelper<T> hashMap)
|
|
{
|
|
_enumerator = new HashMapHelper<T>.Enumerator(ref hashMap);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool MoveNext()
|
|
{
|
|
return _enumerator.MoveNext();
|
|
}
|
|
|
|
public void Reset()
|
|
{
|
|
_enumerator.Reset();
|
|
}
|
|
}
|
|
|
|
private HashMapHelper<T> _helper;
|
|
|
|
public readonly int Count => _helper.Count;
|
|
public readonly int Capacity => _helper.Capacity;
|
|
public readonly bool IsCreated => _helper.IsCreated;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of UnsafeHashSet with a default size of 1 and a persistent allocation handle.
|
|
/// </summary>
|
|
public UnsafeHashSet()
|
|
: this(1, AllocationHandle.Persistent)
|
|
{
|
|
}
|
|
|
|
public UnsafeHashSet(int capacity, AllocationHandle handle, AllocationOption allocationOption = AllocationOption.None)
|
|
{
|
|
_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)
|
|
: this(capacity, AllocationManager.GetAllocationHandle(allocator), allocationOption)
|
|
{
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
[UnscopedRef]
|
|
public Enumerator GetEnumerator()
|
|
{
|
|
return new Enumerator(ref _helper);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds a new value (unless it is already present).
|
|
/// </summary>
|
|
/// <param name="item">The value to add.</param>
|
|
/// <returns>True if the value was not already present.</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool Add(T item)
|
|
{
|
|
return -1 != _helper.TryAdd(item);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes a particular value.
|
|
/// </summary>
|
|
/// <param name="item">The value to remove.</param>
|
|
/// <returns>True if the value was present.</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool Remove(T item)
|
|
{
|
|
return -1 != _helper.TryRemove(item);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if a particular value is present.
|
|
/// </summary>
|
|
/// <param name="item">The value to check for.</param>
|
|
/// <returns>True if the value was present.</returns>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public bool Contains(T item)
|
|
{
|
|
return -1 != _helper.Find(item);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets the capacity to match what it would be if it had been originally initialized with all its entries.
|
|
/// </summary>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void TrimExcess()
|
|
{
|
|
_helper.TrimExcess();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an array with a copy of this set's values (in no particular order).
|
|
/// </summary>
|
|
/// <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>
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public UnsafeArray<T> ToUnsafeArray(AllocationHandle allocationHandle)
|
|
{
|
|
return _helper.GetKeyArray(allocationHandle);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void Resize(int newSize, AllocationOption option = AllocationOption.None)
|
|
{
|
|
_helper.Resize(newSize);
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public void Clear()
|
|
{
|
|
_helper.Clear();
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public readonly void* GetUnsafePtr()
|
|
{
|
|
return _helper.Buffer;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_helper.Dispose();
|
|
}
|
|
}
|