Explorar o código

更新NativeCollection 添加Map类 修复bug (#488)

susices %!s(int64=2) %!d(string=hai) anos
pai
achega
9849f27cae
Modificáronse 31 ficheiros con 1133 adicións e 148 borrados
  1. 1 1
      Unity/Assets/Scripts/ThirdParty/NativeCollection/HashSet.cs
  2. 5 3
      Unity/Assets/Scripts/ThirdParty/NativeCollection/List.cs
  3. 94 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Map.cs
  4. 1 1
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Map.cs.meta
  5. 6 3
      Unity/Assets/Scripts/ThirdParty/NativeCollection/MultiMap.cs
  6. 34 5
      Unity/Assets/Scripts/ThirdParty/NativeCollection/NativeMemoryHelper.cs
  7. 5 4
      Unity/Assets/Scripts/ThirdParty/NativeCollection/NativePool.cs
  8. 6 4
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Queue.cs
  9. 5 3
      Unity/Assets/Scripts/ThirdParty/NativeCollection/SortedSet.cs
  10. 5 4
      Unity/Assets/Scripts/ThirdParty/NativeCollection/Stack.cs
  11. 6 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/ThrowHelper.cs
  12. 113 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnOrderMap.cs
  13. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnOrderMap.cs.meta
  14. 0 76
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs
  15. 46 11
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashSet.cs
  16. 14 2
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/List.cs
  17. 8 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map.meta
  18. 113 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/Map.cs
  19. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/Map.cs.meta
  20. 38 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/MapPair.cs
  21. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/MapPair.cs.meta
  22. 11 9
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMap.cs
  23. 2 2
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMapPair.cs
  24. 3 3
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/NativePool.cs
  25. 2 2
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Queue.cs
  26. 1 1
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/Node.cs
  27. 27 9
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/SortedSet.cs
  28. 3 5
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Stack.cs
  29. 8 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/UnOrderMap.meta
  30. 532 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/UnOrderMap/UnOrderMap.cs
  31. 11 0
      Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/UnOrderMap/UnOrderMap.cs.meta

+ 1 - 1
Unity/Assets/Scripts/ThirdParty/NativeCollection/HashSet.cs

@@ -71,7 +71,7 @@ namespace NativeCollection
         {
             _hashSet->Dispose();
             NativeMemoryHelper.Free(_hashSet);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.HashSet<T>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.HashSet<T>>());
             IsDisposed = true;
         }
     }

+ 5 - 3
Unity/Assets/Scripts/ThirdParty/NativeCollection/List.cs

@@ -9,9 +9,11 @@ namespace NativeCollection
 {
     private UnsafeType.List<T>* _list;
     private const int _defaultCapacity = 10;
+    private int _capacity;
     public List(int capacity = _defaultCapacity)
     {
-        _list = UnsafeType.List<T>.Create(capacity);
+        _capacity = capacity;
+        _list = UnsafeType.List<T>.Create(_capacity);
         IsDisposed = false;
     }
     
@@ -94,7 +96,7 @@ namespace NativeCollection
         {
             _list->Dispose();
             NativeMemoryHelper.Free(_list);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.List<T>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.List<T>>());
             IsDisposed = true;
         }
     }
@@ -103,7 +105,7 @@ namespace NativeCollection
     {
         if (IsDisposed)
         {
-            _list = UnsafeType.List<T>.Create(_defaultCapacity);
+            _list = UnsafeType.List<T>.Create(_capacity);
             IsDisposed = false;
         }
     }

+ 94 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/Map.cs

@@ -0,0 +1,94 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using NativeCollection.UnsafeType;
+
+namespace NativeCollection
+{
+    public unsafe class Map<T, K> : IEnumerable<MapPair<T, K>>, INativeCollectionClass
+        where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+    {
+        private const int _defaultPoolSize = 50;
+        private int _poolSize;
+        private UnsafeType.Map<T, K>* _map;
+    
+        public Map(int maxPoolSize = _defaultPoolSize)
+        {
+            _poolSize = maxPoolSize;
+            _map = UnsafeType.Map<T, K>.Create(_poolSize);
+            IsDisposed = false;
+        }
+    
+        public K this[T key]
+        {
+            get => (*_map)[key];
+            set => (*_map)[key] = value;
+        }
+    
+        public int Count => _map->Count;
+    
+        IEnumerator<MapPair<T, K>> IEnumerable<MapPair<T, K>>.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    
+        public void Dispose()
+        {
+            if (IsDisposed) return;
+            if (_map != null)
+            {
+                _map->Dispose();
+                NativeMemoryHelper.Free(_map);
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.Map<T, K>>());
+                IsDisposed = true;
+            }
+        }
+    
+        public void ReInit()
+        {
+            if (IsDisposed)
+            {
+                _map = UnsafeType.Map<T, K>.Create(_poolSize);
+                IsDisposed = false;
+            }
+        }
+    
+        public bool IsDisposed { get; private set; }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Add(T key, K value)
+        {
+            _map->Add(key, value);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Remove(T key)
+        {
+            return _map->Remove(key);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Clear()
+        {
+            _map->Clear();
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public UnsafeType.SortedSet<MapPair<T, K>>.Enumerator GetEnumerator()
+        {
+            return _map->GetEnumerator();
+        }
+    
+        ~Map()
+        {
+            Dispose();
+        }
+    }
+}
+

+ 1 - 1
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs.meta → Unity/Assets/Scripts/ThirdParty/NativeCollection/Map.cs.meta

@@ -1,5 +1,5 @@
 fileFormatVersion: 2
-guid: 49e35b184dd60c64f8593512d7018a28
+guid: 6f3e3ddf9d2240e47bf659805f2c4e50
 MonoImporter:
   externalObjects: {}
   serializedVersion: 2

+ 6 - 3
Unity/Assets/Scripts/ThirdParty/NativeCollection/MultiMap.cs

@@ -12,10 +12,13 @@ namespace NativeCollection
     private UnsafeType.MultiMap<T, K>* _multiMap;
 
     private const int _defaultPoolSize = 200;
+
+    private int _poolSize;
     
     public MultiMap(int maxPoolSize = _defaultPoolSize)
     {
-        _multiMap = UnsafeType.MultiMap<T, K>.Create(maxPoolSize);
+        _poolSize = maxPoolSize;
+        _multiMap = UnsafeType.MultiMap<T, K>.Create(_poolSize);
         IsDisposed = false;
     }
     
@@ -73,7 +76,7 @@ namespace NativeCollection
         {
             _multiMap->Dispose();
             NativeMemoryHelper.Free(_multiMap);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.MultiMap<T,K>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.MultiMap<T,K>>());
             IsDisposed = true;
         }
     }
@@ -82,7 +85,7 @@ namespace NativeCollection
     {
         if (IsDisposed)
         {
-            _multiMap = UnsafeType.MultiMap<T, K>.Create(_defaultPoolSize);
+            _multiMap = UnsafeType.MultiMap<T, K>.Create(_poolSize);
             IsDisposed = false;
         }
     }

+ 34 - 5
Unity/Assets/Scripts/ThirdParty/NativeCollection/NativeMemoryHelper.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
@@ -9,7 +10,7 @@ namespace NativeCollection
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void* Alloc(UIntPtr byteCount)
         {
-            GC.AddMemoryPressure((long)byteCount);
+            AddNativeMemoryByte((long)byteCount);
 #if NET6_0_OR_GREATER
             return NativeMemory.Alloc(byteCount);
 #else
@@ -20,7 +21,7 @@ namespace NativeCollection
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void* Alloc(UIntPtr elementCount, UIntPtr elementSize)
         {
-            GC.AddMemoryPressure((long)((long)elementCount * (long)elementSize));
+            AddNativeMemoryByte((long)((long)elementCount * (long)elementSize));
 #if NET6_0_OR_GREATER
             return NativeMemory.Alloc(elementCount, elementSize);
 #else
@@ -31,7 +32,7 @@ namespace NativeCollection
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void* AllocZeroed(UIntPtr byteCount)
         {
-            GC.AddMemoryPressure((long)byteCount);
+            AddNativeMemoryByte((long)byteCount);
 #if NET6_0_OR_GREATER
             return NativeMemory.AllocZeroed(byteCount);
 #else
@@ -44,8 +45,7 @@ namespace NativeCollection
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static void* AllocZeroed(UIntPtr elementCount, UIntPtr elementSize)
         {
-            GC.AddMemoryPressure((long)((long)elementCount * (long)elementSize));
-        
+            AddNativeMemoryByte((long)((long)elementCount * (long)elementSize));
 #if NET6_0_OR_GREATER
             return NativeMemory.AllocZeroed(elementCount, elementSize);
 #else
@@ -63,6 +63,35 @@ namespace NativeCollection
             NativeMemory.Free(ptr);
 #else
         Marshal.FreeHGlobal(new IntPtr(ptr));
+#endif
+        }
+        
+#if MEMORY_PROFILE
+        public static long NativeMemoryBytes;
+#endif
+        
+        public static void AddNativeMemoryByte(long size)
+        {
+            GC.AddMemoryPressure((long)size);
+#if MEMORY_PROFILE
+            NativeMemoryBytes += size;
+#endif
+        }
+        
+        public static void RemoveNativeMemoryByte(long size)
+        {
+            GC.RemoveMemoryPressure(size);
+#if MEMORY_PROFILE
+            NativeMemoryBytes -= size;
+#endif
+        }
+
+        public static long GetNativeMemoryBytes()
+        {
+#if MEMORY_PROFILE
+            return NativeMemoryBytes;
+#else
+            return 0;
 #endif
         }
     }    

+ 5 - 4
Unity/Assets/Scripts/ThirdParty/NativeCollection/NativePool.cs

@@ -8,10 +8,11 @@ namespace NativeCollection
     {
         private UnsafeType.NativePool<T>* _nativePool;
         private const int _defaultPoolSize = 200;
-    
+        private int _poolSize;
         public NativePool(int maxPoolSize = _defaultPoolSize)
         {
-            _nativePool = UnsafeType.NativePool<T>.Create(maxPoolSize);
+            _poolSize = maxPoolSize;
+            _nativePool = UnsafeType.NativePool<T>.Create(_poolSize);
             IsDisposed = false;
         }
         
@@ -37,7 +38,7 @@ namespace NativeCollection
             {
                 _nativePool->Dispose();
                 NativeMemoryHelper.Free(_nativePool);
-                GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.NativePool<T>>());
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.NativePool<T>>());
                 IsDisposed = true;
             }
         }
@@ -46,7 +47,7 @@ namespace NativeCollection
         {
             if (IsDisposed)
             {
-                _nativePool = UnsafeType.NativePool<T>.Create(_defaultPoolSize);
+                _nativePool = UnsafeType.NativePool<T>.Create(_poolSize);
                 IsDisposed = false;
             }
         }

+ 6 - 4
Unity/Assets/Scripts/ThirdParty/NativeCollection/Queue.cs

@@ -6,10 +6,12 @@ namespace NativeCollection
     public unsafe class Queue<T> : INativeCollectionClass where T : unmanaged
     {
         private UnsafeType.Queue<T>* _queue;
-    
+        private const int _defaultCapacity = 10;
+        private int _capacity;
         public Queue(int capacity = 10)
         {
-            _queue = UnsafeType.Queue<T>.Create(capacity);
+            _capacity = capacity;
+            _queue = UnsafeType.Queue<T>.Create(_capacity);
             IsDisposed = false;
         }
     
@@ -25,7 +27,7 @@ namespace NativeCollection
             {
                 _queue->Dispose();
                 NativeMemoryHelper.Free(_queue);
-                GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Queue<T>>());
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.Queue<T>>());
                 IsDisposed = true;
             }
         }
@@ -77,7 +79,7 @@ namespace NativeCollection
         {
             if (IsDisposed)
             {
-                _queue = UnsafeType.Queue<T>.Create();
+                _queue = UnsafeType.Queue<T>.Create(_capacity);
                 IsDisposed = false;
             }
         }

+ 5 - 3
Unity/Assets/Scripts/ThirdParty/NativeCollection/SortedSet.cs

@@ -9,9 +9,11 @@ namespace NativeCollection
 {
     private UnsafeType.SortedSet<T>* _sortedSet;
     private const int _defaultNodePoolSize = 200;
+    private int _poolSize;
     public SortedSet(int nodePoolSize = _defaultNodePoolSize)
     {
-        _sortedSet = UnsafeType.SortedSet<T>.Create(nodePoolSize);
+        _poolSize = nodePoolSize;
+        _sortedSet = UnsafeType.SortedSet<T>.Create(_poolSize);
         IsDisposed = false;
     }
     IEnumerator<T> IEnumerable<T>.GetEnumerator()
@@ -81,7 +83,7 @@ namespace NativeCollection
         {
             _sortedSet->Dispose();
             NativeMemoryHelper.Free(_sortedSet);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.SortedSet<T>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.SortedSet<T>>());
             IsDisposed = true;
         }
     }
@@ -90,7 +92,7 @@ namespace NativeCollection
     {
         if (IsDisposed)
         {
-            _sortedSet = UnsafeType.SortedSet<T>.Create(_defaultNodePoolSize);
+            _sortedSet = UnsafeType.SortedSet<T>.Create(_poolSize);
             IsDisposed = false;
         }
     }

+ 5 - 4
Unity/Assets/Scripts/ThirdParty/NativeCollection/Stack.cs

@@ -7,10 +7,11 @@ namespace NativeCollection
     {
         private const int _defaultCapacity = 10;
         private UnsafeType.Stack<T>* _stack;
-    
+        private int _capacity;
         public Stack(int initialCapacity = _defaultCapacity)
         {
-            _stack = UnsafeType.Stack<T>.Create(initialCapacity);
+            _capacity = initialCapacity;
+            _stack = UnsafeType.Stack<T>.Create(_capacity);
             IsDisposed = false;
         }
     
@@ -26,7 +27,7 @@ namespace NativeCollection
             {
                 _stack->Dispose();
                 NativeMemoryHelper.Free(_stack);
-                GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Stack<T>>());
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.Stack<T>>());
                 IsDisposed = true;
             }
         }
@@ -76,7 +77,7 @@ namespace NativeCollection
         {
             if (IsDisposed)
             {
-                _stack = UnsafeType.Stack<T>.Create(_defaultCapacity);
+                _stack = UnsafeType.Stack<T>.Create(_capacity);
                 IsDisposed = false;
             }
         }

+ 6 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/ThrowHelper.cs

@@ -79,6 +79,12 @@ namespace NativeCollection
         {
             throw new InvalidOperationException("_version != _tree.version");
         }
+
+        [DoesNotReturn]
+        public static void ThrowAddingDuplicateWithKeyArgumentException()
+        {
+            throw new ArgumentException("AddingDuplicateWithKey");
+        }
     }
 }
 

+ 113 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnOrderMap.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using NativeCollection.UnsafeType;
+
+namespace NativeCollection
+{
+    public unsafe class UnOrderMap<T, K> : IEnumerable<MapPair<T, K>>, INativeCollectionClass
+        where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+    {
+private int _capacity;
+        private UnsafeType.UnOrderMap<T, K>* _unOrderMap;
+
+        public UnOrderMap(int initCapacity = 0)
+        {
+            _capacity = initCapacity;
+            _unOrderMap = UnsafeType.UnOrderMap<T, K>.Create(_capacity);
+            IsDisposed = false;
+        }
+
+        public K this[T key]
+        {
+            get => (*_unOrderMap)[key];
+            set => (*_unOrderMap)[key] = value;
+        }
+        
+        public int Count => _unOrderMap->Count;
+        
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Add(in T key, K value)
+        {
+            _unOrderMap->Add(key, value);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Remove(in T key)
+        {
+            return _unOrderMap->Remove(key);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void Clear()
+        {
+            _unOrderMap->Clear();
+        }
+        
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool ContainsKey(in T key)
+        {
+            return _unOrderMap->ContainsKey(key);
+        }
+        
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool TryGetValue(in T key, out K value)
+        {
+            bool contains =  _unOrderMap->TryGetValue(key, out var actualValue);
+            if (contains)
+            {
+                value = actualValue;
+                return true;
+            }
+            value = default;
+            return false;
+        }
+
+        
+        IEnumerator<MapPair<T, K>> IEnumerable<MapPair<T, K>>.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+        
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public UnsafeType.UnOrderMap<T,K>.Enumerator GetEnumerator()
+        {
+            return _unOrderMap->GetEnumerator();
+        }
+
+        public void Dispose()
+        {
+            if (IsDisposed) return;
+            if (_unOrderMap != null)
+            {
+                _unOrderMap->Dispose();
+                NativeMemoryHelper.Free(_unOrderMap);
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.UnOrderMap<T, K>>());
+                IsDisposed = true;
+            }
+        }
+
+        public void ReInit()
+        {
+            if (IsDisposed)
+            {
+                _unOrderMap = UnsafeType.UnOrderMap<T, K>.Create(_capacity);
+                IsDisposed = false;
+            }
+        }
+
+        public bool IsDisposed { get; private set; }
+        
+        ~UnOrderMap()
+        {
+            Dispose();
+        }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnOrderMap.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: f86f1ca0258ed6b4185f523c8f7fcfea
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 76
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Dictionary.cs

@@ -1,76 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace NativeCollection.UnsafeType
-{
-    public unsafe struct Dictionary<TKey, TValue> : IDictionary<TKey, TValue> where TKey : unmanaged, IEquatable<TKey> where TValue : unmanaged, IEquatable<TValue>
-    {
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            throw new NotImplementedException();
-        }
-    
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
-    
-        public void Add(KeyValuePair<TKey, TValue> item)
-        {
-            throw new NotImplementedException();
-        }
-       
-        public void Clear()
-        {
-            throw new NotImplementedException();
-        }
-    
-        public bool Contains(KeyValuePair<TKey, TValue> item)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public bool Remove(KeyValuePair<TKey, TValue> item)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public int Count { get; }
-        public bool IsReadOnly { get; }
-        public void Add(TKey key, TValue value)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public bool ContainsKey(TKey key)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public bool Remove(TKey key)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            throw new NotImplementedException();
-        }
-    
-        public TValue this[TKey key]
-        {
-            get => throw new NotImplementedException();
-            set => throw new NotImplementedException();
-        }
-    
-        public ICollection<TKey> Keys { get; }
-        public ICollection<TValue> Values { get; }
-    }
-}
-

+ 46 - 11
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/HashSet.cs

@@ -6,8 +6,7 @@ using System.Runtime.CompilerServices;
 using System.Text;
 
 namespace NativeCollection.UnsafeType
-{
-    public unsafe struct HashSet<T> : ICollection<T>, IDisposable where T : unmanaged, IEquatable<T>
+{public unsafe struct HashSet<T> : ICollection<T>, IDisposable where T : unmanaged, IEquatable<T>
 {
     /// <summary>Cutoff point for stackallocs. This corresponds to the number of ints.</summary>
     private const int StackAllocThreshold = 100;
@@ -35,7 +34,6 @@ namespace NativeCollection.UnsafeType
     private int _freeList;
     private int _freeCount;
     private int _version;
-    private static IEqualityComparer<T> _comparer = EqualityComparer<T>.Default;
 
     public static HashSet<T>* Create(int capacity = 0)
     {
@@ -49,6 +47,9 @@ namespace NativeCollection.UnsafeType
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public bool Add(T item) => AddIfNotPresent(item, out _);
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool AddRef(in T item) => AddIfNotPresent(item, out _);
 
     IEnumerator<T> IEnumerable<T>.GetEnumerator()
     {
@@ -91,6 +92,12 @@ namespace NativeCollection.UnsafeType
     {
         return FindItemIndex(item) >= 0;
     }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool ContainsRef(in T item)
+    {
+        return FindItemIndex(item) >= 0;
+    }
 
     #endregion
 
@@ -100,7 +107,7 @@ namespace NativeCollection.UnsafeType
         throw new NotImplementedException();
     }
     
-    public bool Remove(T item)
+    public bool RemoveRef(in T item)
     {
         //if (_buckets == null) return false;
         var entries = _entries;
@@ -150,6 +157,34 @@ namespace NativeCollection.UnsafeType
 
         return false;
     }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        return RemoveRef(item);
+    }
+
+    public bool TryGetValue(in T equalValue, out T actualValue)
+    {
+        int index = FindItemIndex(equalValue);
+        if (index>=0)
+        {
+            actualValue = _entries[index].Value;
+            return true;
+        }
+        actualValue = default;
+        return false;
+    }
+
+    internal T* GetValuePointer(in T key)
+    {
+        int index = FindItemIndex(key);
+        if (index>=0)
+        {
+            return &(_entries + index)->Value;
+        }
+        return null;
+    }
 
     public int Count => _count - _freeCount;
     bool ICollection<T>.IsReadOnly => false;
@@ -157,10 +192,10 @@ namespace NativeCollection.UnsafeType
     public void Dispose()
     {
         NativeMemoryHelper.Free(_buckets);
-        GC.RemoveMemoryPressure(Unsafe.SizeOf<int>()*_bucketLength);
+        NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<int>()*_bucketLength);
         
         NativeMemoryHelper.Free(_entries);
-        GC.RemoveMemoryPressure(Unsafe.SizeOf<Entry>()*_entryLength);
+        NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<Entry>()*_entryLength);
     }
     
     #region Helper methods
@@ -193,7 +228,7 @@ namespace NativeCollection.UnsafeType
     /// <param name="location">The index into <see cref="_entries" /> of the element.</param>
     /// <returns>true if the element is added to the <see cref="HashSet{T}" /> object; false if the element is already present.</returns>
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    private bool AddIfNotPresent(T value, out int location)
+    private bool AddIfNotPresent(in T value, out int location)
     {
         //Console.WriteLine($"AddIfNotPresent:{value}");
         //if (_buckets == null) Initialize(0);
@@ -218,7 +253,7 @@ namespace NativeCollection.UnsafeType
             // Console.WriteLine($"i:{i}");
             ref Entry entry = ref _entries[i];
             // Console.WriteLine($"entry.HashCode:{entry.HashCode} hashCode:{hashCode} Equals:{comparer.Equals(entry.Value, value)}");
-            if (entry.HashCode == hashCode && value.Equals(value))
+            if (entry.HashCode == hashCode && entry.Value.Equals(value))
             {
                 location = i;
                 return false;
@@ -328,7 +363,7 @@ namespace NativeCollection.UnsafeType
             // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails
             var newBucket = (int*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<int>() * newSize));
             NativeMemoryHelper.Free(_buckets);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<int>()*_bucketLength);
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<int>()*_bucketLength);
             _buckets = newBucket;
             _bucketLength = newSize;
 #if TARGET_64BIT
@@ -346,7 +381,7 @@ namespace NativeCollection.UnsafeType
                 }
             }
             NativeMemoryHelper.Free(_entries);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<Entry>()*_entryLength);
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<Entry>()*_entryLength);
             _entries = newEntries;
             _entryLength = newSize;
             
@@ -355,7 +390,7 @@ namespace NativeCollection.UnsafeType
         
         /// <summary>Gets the index of the item in <see cref="_entries"/>, or -1 if it's not in the set.</summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        private int FindItemIndex(T item)
+        private int FindItemIndex(in T item)
         {
             //if (_buckets == null) return -1;
             var entries = _entries;

+ 14 - 2
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/List.cs

@@ -61,7 +61,7 @@ namespace NativeCollection.UnsafeType
                     if (Count > 0)
                         Unsafe.CopyBlockUnaligned(newArray, _items, (uint)(_arrayLength * Unsafe.SizeOf<T>()));
                     NativeMemoryHelper.Free(_items);
-                    GC.RemoveMemoryPressure(Unsafe.SizeOf<T>() * _arrayLength);
+                    NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<T>() * _arrayLength);
                     _items = newArray;
                     _arrayLength = value;
                 }
@@ -76,6 +76,12 @@ namespace NativeCollection.UnsafeType
     
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public void Add(T value)
+    {
+        AddRef(value);
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void AddRef(T value)
     {
         var array = _items;
         var size = Count;
@@ -98,6 +104,12 @@ namespace NativeCollection.UnsafeType
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     public bool Remove(T item)
+    {
+        return RemoveRef(item);
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool RemoveRef(in T item)
     {
         var index = IndexOf(item);
         //Console.WriteLine($"index: {index}");
@@ -277,7 +289,7 @@ namespace NativeCollection.UnsafeType
     public void Dispose()
     {
         NativeMemoryHelper.Free(_items);
-        GC.RemoveMemoryPressure(_arrayLength * Unsafe.SizeOf<T>());
+        NativeMemoryHelper.RemoveNativeMemoryByte(_arrayLength * Unsafe.SizeOf<T>());
     }
 
 

+ 8 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 4444b255d2b878f47895e6e0a19ba413
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 113 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/Map.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct Map<T,K> :IEnumerable<MapPair<T, K>>, IDisposable where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+{
+    private UnsafeType.SortedSet<MapPair<T, K>>* _sortedSet;
+    
+    public static Map<T, K>* Create(int maxPoolSize)
+    {
+        Map<T, K>* map = (Map<T, K>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<Map<T, K>>());
+        map->_sortedSet = UnsafeType.SortedSet<MapPair<T, K>>.Create(maxPoolSize);
+        return map;
+    }
+    
+    public K this[T key] {
+        get
+        {
+            var pair = new MapPair<T, K>(key);
+            var node = _sortedSet->FindNode(pair);
+            if (node!=null)
+            {
+                return node->Item.Value;
+            }
+            return default;
+        }
+        set
+        {
+            var pair = new MapPair<T, K>(key,value);
+            var node = _sortedSet->FindNode(pair);
+            if (node!=null)
+            {
+                node->Item._value = value;
+            }
+            else
+            {
+                _sortedSet->Add(pair);
+            }
+        }
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Add(T key, K value)
+    {
+        var mapPair = new MapPair<T, K>(key,value);
+        _sortedSet->Add(mapPair);
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        _sortedSet->Clear();
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool ContainsKey(T key)
+    {
+        return _sortedSet->Contains(new MapPair<T, K>(key));
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T key)
+    {
+        return _sortedSet->Remove(new MapPair<T, K>(key));
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool TryGetValue(T key, out K value)
+    {
+        var node = _sortedSet->FindNode(new MapPair<T, K>(key));
+        if (node==null)
+        {
+            value = default;
+            return false;
+        }
+        value = node->Item.Value;
+        return true;
+    }
+    
+    public int Count => _sortedSet->Count;
+    
+    IEnumerator<MapPair<T, K>> IEnumerable<MapPair<T, K>>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public UnsafeType.SortedSet<MapPair<T, K>>.Enumerator GetEnumerator()
+    {
+        return new UnsafeType.SortedSet<MapPair<T, K>>.Enumerator(_sortedSet);
+    }
+
+    public void Dispose()
+    {
+        if (_sortedSet != null)
+        {
+            _sortedSet->Dispose();
+            NativeMemoryHelper.Free(_sortedSet);
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.SortedSet<MapPair<T, K>>>());
+        }
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/Map.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dfec185ba796bab42b88bfe39468a0d5
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 38 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/MapPair.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Runtime.CompilerServices;
+
+namespace NativeCollection.UnsafeType
+{
+    public unsafe struct MapPair<T, K> : IEquatable<MapPair<T, K>>, IComparable<MapPair<T, K>>
+        where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+    {
+        public T Key { get; private set; }
+        public K Value => _value;
+
+        internal K _value;
+
+        public MapPair(T key,K value = default)
+        {
+            Key = key;
+            _value = value;
+        }
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public bool Equals(MapPair<T, K> other)
+        {
+            return Key.Equals(other.Key);
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public int CompareTo(MapPair<T, K> other)
+        {
+            return Key.CompareTo(other.Key);
+        }
+    
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public override int GetHashCode()
+        {
+            return Key.GetHashCode();
+        }
+    }
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Map/MapPair.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 56d8c7a06e8ab9d46857feace3022f27
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 11 - 9
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMap.cs

@@ -34,7 +34,7 @@ namespace NativeCollection.UnsafeType
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public void Add(T key, K value)
+    public void Add(in T key,in K value)
     {
         var list = new MultiMapPair<T, K>(key);
         var node = _sortedSet->FindNode(list);
@@ -45,35 +45,37 @@ namespace NativeCollection.UnsafeType
         else
         {
             list = MultiMapPair<T, K>.Create(key,_listPool);
-            _sortedSet->Add(list);
+            _sortedSet->AddRef(list);
         }
-        list.Value.Add(value);
+        list.Value.AddRef(value);
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public bool Remove(T key, K value)
+    public bool Remove(in T key,in K value)
     {
         var list = new MultiMapPair<T, K>(key);
         var node = _sortedSet->FindNode(list);
 
         if (node == null) return false;
         list = node->Item;
-        if (!list.Value.Remove(value)) return false;
+        if (!list.Value.RemoveRef(value)) return false;
 
         if (list.Value.Count == 0) Remove(key);
 
         return true;
     }
+    
+    
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    public bool Remove(T key)
+    public bool Remove(in T key)
     {
         var list = new MultiMapPair<T, K>(key);
         SortedSet<MultiMapPair<T, K>>.Node* node = _sortedSet->FindNode(list);
 
         if (node == null) return false;
         list = node->Item;
-        var sortedSetRemove = _sortedSet->Remove(list);
+        var sortedSetRemove = _sortedSet->RemoveRef(list);
         list.Dispose(_listPool);
         return sortedSetRemove;
     }
@@ -110,14 +112,14 @@ namespace NativeCollection.UnsafeType
         {
             _sortedSet->Dispose();
             NativeMemoryHelper.Free(_sortedSet);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.SortedSet<MultiMapPair<T, K>>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.SortedSet<MultiMapPair<T, K>>>());
         }
 
         if (_listPool!=null)
         {
             _listPool->Dispose();
             NativeMemoryHelper.Free(_listPool);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<NativePool<List<K>>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<NativePool<List<K>>>());
         }
     }
 }

+ 2 - 2
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/MultiMap/MultiMapPair.cs

@@ -7,7 +7,7 @@ namespace NativeCollection.UnsafeType
         where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
     {
         private UnsafeType.List<K>* _value;
-    
+        
         public T Key { get; private set; }
     
         public ref UnsafeType.List<K> Value => ref Unsafe.AsRef<UnsafeType.List<K>>(_value);
@@ -19,7 +19,7 @@ namespace NativeCollection.UnsafeType
         }
     
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static MultiMapPair<T, K> Create(T key, NativePool<List<K>>* pool)
+        public static MultiMapPair<T, K> Create(in T key, NativePool<List<K>>* pool)
         {
             var pair = new MultiMapPair<T, K>(key);
             var list = pool->Alloc();

+ 3 - 3
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/NativePool.cs

@@ -40,7 +40,7 @@ namespace NativeCollection.UnsafeType
             {
                 ptr->Dispose();
                 NativeMemoryHelper.Free(ptr);
-                GC.RemoveMemoryPressure(Unsafe.SizeOf<T>());
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<T>());
                 return;
             }
             ptr->OnReturnToPool();
@@ -54,7 +54,7 @@ namespace NativeCollection.UnsafeType
                 T* item = (T*)ptr;
                 item->Dispose();
                 NativeMemoryHelper.Free(item);
-                GC.RemoveMemoryPressure(Unsafe.SizeOf<T>());
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<T>());
             }
         }
     
@@ -63,7 +63,7 @@ namespace NativeCollection.UnsafeType
             Clear();
             _stack->Dispose();
             NativeMemoryHelper.Free(_stack);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<Stack<T>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<Stack<T>>());
         }
     }
 }

+ 2 - 2
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Queue.cs

@@ -133,7 +133,7 @@ namespace NativeCollection.UnsafeType
         }
 
         NativeMemoryHelper.Free(_array);
-        GC.RemoveMemoryPressure(length * Unsafe.SizeOf<T>());
+        NativeMemoryHelper.RemoveNativeMemoryByte(length * Unsafe.SizeOf<T>());
         _array = destinationArray;
         _head = 0;
         _tail = Count == capacity ? 0 : Count;
@@ -155,7 +155,7 @@ namespace NativeCollection.UnsafeType
         if (_array!=null)
         {
             NativeMemoryHelper.Free(_array);
-            GC.RemoveMemoryPressure(length * Unsafe.SizeOf<T>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(length * Unsafe.SizeOf<T>());
         }
     }
 }

+ 1 - 1
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/Node.cs

@@ -154,7 +154,7 @@ namespace NativeCollection.UnsafeType
 
             pendingNodes->Dispose();
             NativeMemoryHelper.Free(pendingNodes);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Stack<NodeSourceTarget>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.Stack<NodeSourceTarget>>());
             return newRoot;
         }
 

+ 27 - 9
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/SortedSet/SortedSet.cs

@@ -16,7 +16,7 @@ namespace NativeCollection.UnsafeType
     private NativePool<Node>* _nodePool;
     private NativePool<Stack<IntPtr>>* _stackPool;
     private int _version;
-    private const int _defaultNodePoolSize = 200;
+    private const int _defaultNodePoolSize = 50;
     public static SortedSet<T>* Create(int nodePoolSize = _defaultNodePoolSize)
     {
         var sortedSet = (SortedSet<T>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<SortedSet<T>>());
@@ -83,6 +83,12 @@ namespace NativeCollection.UnsafeType
         return DoRemove(item);
     }
 
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool RemoveRef(in T item)
+    {
+        return DoRemove(item);
+    }
+
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
     void ICollection<T>.Add(T item)
     {
@@ -98,12 +104,12 @@ namespace NativeCollection.UnsafeType
             if (enumerator.CurrentPointer != null)
             {
                 NativeMemoryHelper.Free(enumerator.CurrentPointer);
-                GC.RemoveMemoryPressure(Unsafe.SizeOf<Node>());
+                NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<Node>());
                 nodeCount++;
             }
         } while (enumerator.MoveNext());
 
-        if (nodeCount != 0) GC.RemoveMemoryPressure(nodeCount * Unsafe.SizeOf<Node>());
+        if (nodeCount != 0) NativeMemoryHelper.RemoveNativeMemoryByte(nodeCount * Unsafe.SizeOf<Node>());
 
         _root = null;
         _count = 0;
@@ -118,6 +124,12 @@ namespace NativeCollection.UnsafeType
     {
         return FindNode(item) != null;
     }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool ContainsRef(in T item)
+    {
+        return FindNode(item) != null;
+    }
 
     IEnumerator<T> IEnumerable<T>.GetEnumerator()
     {
@@ -136,13 +148,13 @@ namespace NativeCollection.UnsafeType
         {
             _nodePool->Dispose();
             NativeMemoryHelper.Free(_nodePool);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<NativePool<Node>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<NativePool<Node>>());
         }
         if (_stackPool!=null)
         {
             _stackPool->Dispose();
             NativeMemoryHelper.Free(_stackPool);
-            GC.RemoveMemoryPressure(Unsafe.SizeOf<NativePool<Stack<IntPtr>>>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<NativePool<Stack<IntPtr>>>());
         }
         _version = 0;
     }
@@ -214,7 +226,7 @@ namespace NativeCollection.UnsafeType
         }
         stack->Dispose();
         NativeMemoryHelper.Free(stack);
-        GC.RemoveMemoryPressure(Unsafe.SizeOf<UnsafeType.Stack<IntPtr>>());
+        NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<UnsafeType.Stack<IntPtr>>());
         return true;
     }
 
@@ -230,7 +242,7 @@ namespace NativeCollection.UnsafeType
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal bool IsWithinRange(T item)
+    internal bool IsWithinRange(in T item)
     {
         return true;
     }
@@ -241,6 +253,12 @@ namespace NativeCollection.UnsafeType
     {
         return AddIfNotPresent(item);
     }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool AddRef(in T item)
+    {
+        return AddIfNotPresent(item);
+    }
 
     internal bool AddIfNotPresent(in T item)
     {
@@ -308,7 +326,7 @@ namespace NativeCollection.UnsafeType
         return true;
     }
 
-    internal bool DoRemove(T item)
+    internal bool DoRemove(in T item)
     {
         if (_root == null) return false;
 
@@ -504,7 +522,7 @@ namespace NativeCollection.UnsafeType
     }
 
     [MethodImpl(MethodImplOptions.AggressiveInlining)]
-    internal Node* FindNode(T item)
+    internal Node* FindNode(in T item)
     {
         var current = _root;
         while (current != null)

+ 3 - 5
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/Stack.cs

@@ -15,13 +15,11 @@ namespace NativeCollection.UnsafeType
         if (initialCapacity < 0) ThrowHelper.StackInitialCapacityException();
 
         var stack = (Stack<T>*)NativeMemoryHelper.Alloc((UIntPtr)System.Runtime.CompilerServices.Unsafe.SizeOf<Stack<T>>());
-        GC.AddMemoryPressure(System.Runtime.CompilerServices.Unsafe.SizeOf<Stack<T>>());
-
+        
         if (initialCapacity < _defaultCapacity)
             initialCapacity = _defaultCapacity; // Simplify doubling logic in Push.
 
         stack->_array = (T*)NativeMemoryHelper.Alloc((UIntPtr)initialCapacity, (UIntPtr)System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
-        GC.AddMemoryPressure(initialCapacity * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
         stack->ArrayLength = initialCapacity;
         stack->Count = 0;
         stack->_version = 0;
@@ -91,7 +89,7 @@ namespace NativeCollection.UnsafeType
             var newArray = (T*)NativeMemoryHelper.Alloc((UIntPtr)(ArrayLength * 2), (UIntPtr)System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
             System.Runtime.CompilerServices.Unsafe.CopyBlockUnaligned(newArray, _array, (uint)(Count * System.Runtime.CompilerServices.Unsafe.SizeOf<T>()));
             NativeMemoryHelper.Free(_array);
-            GC.RemoveMemoryPressure(ArrayLength * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+            NativeMemoryHelper.RemoveNativeMemoryByte(ArrayLength * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
             _array = newArray;
             ArrayLength = ArrayLength * 2;
         }
@@ -103,7 +101,7 @@ namespace NativeCollection.UnsafeType
     public void Dispose()
     {
         NativeMemoryHelper.Free(_array);
-        GC.RemoveMemoryPressure(ArrayLength * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
+        NativeMemoryHelper.RemoveNativeMemoryByte(ArrayLength * System.Runtime.CompilerServices.Unsafe.SizeOf<T>());
     }
 
     public void OnReturnToPool()

+ 8 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/UnOrderMap.meta

@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: eeabde77b436b004ea4ec6d8b298ea11
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 532 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/UnOrderMap/UnOrderMap.cs

@@ -0,0 +1,532 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Text;
+
+namespace NativeCollection.UnsafeType
+{
+public unsafe struct UnOrderMap<T,K> : IEnumerable<MapPair<T, K>>
+    where T : unmanaged, IEquatable<T>, IComparable<T> where K : unmanaged, IEquatable<K>
+{
+    /// <summary>Cutoff point for stackallocs. This corresponds to the number of ints.</summary>
+    private const int StackAllocThreshold = 100;
+
+    /// <summary>
+    ///     When constructing a hashset from an existing collection, it may contain duplicates,
+    ///     so this is used as the max acceptable excess ratio of capacity to count. Note that
+    ///     this is only used on the ctor and not to automatically shrink if the hashset has, e.g,
+    ///     a lot of adds followed by removes. Users must explicitly shrink by calling TrimExcess.
+    ///     This is set to 3 because capacity is acceptable as 2x rounded up to nearest prime.
+    /// </summary>
+    private const int ShrinkThreshold = 3;
+
+    private const int StartOfFreeList = -3;
+
+    private UnOrderMap<T,K>* _self;
+    private int* _buckets;
+    private int _bucketLength;
+    private Entry* _entries;
+    private int _entryLength;
+#if TARGET_64BIT
+        private ulong _fastModMultiplier;
+#endif
+    private int _count;
+    private int _freeList;
+    private int _freeCount;
+    private int _version;
+
+    public static UnOrderMap<T,K>* Create(int capacity = 0)
+    {
+        UnOrderMap<T,K>* unOrderMap = (UnOrderMap<T,K>*)NativeMemoryHelper.Alloc((UIntPtr)Unsafe.SizeOf<UnOrderMap<T,K>>());
+        unOrderMap->_buckets = null;
+        unOrderMap->_entries = null;
+        unOrderMap->_self = unOrderMap;
+        unOrderMap->Initialize(capacity);
+        return unOrderMap;
+    }
+    
+    public K this[T key]
+    {
+        get
+        {
+            bool contains = TryGetValue(key, out var value);
+            if (contains)
+            {
+                return value;
+            }
+            return default;
+        }
+        set
+        {
+            bool modified = TryInsert(key, value, InsertionBehavior.OverwriteExisting);
+            Debug.Assert(modified);
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Add(T key,K value) => AddRef(key,value);
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool AddRef(in T key, in K value) => TryInsert(key,value, InsertionBehavior.ThrowOnExisting);
+
+    IEnumerator<MapPair<T, K>> IEnumerable<MapPair<T, K>>.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+        return GetEnumerator();
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public Enumerator GetEnumerator() => new Enumerator(_self);
+
+    #region ICollection<T> methods
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void Clear()
+    {
+        int count = _count;
+        if (count > 0)
+        {
+            Debug.Assert(_buckets != null, "_buckets should be non-null");
+            Debug.Assert(_entries != null, "_entries should be non-null");
+            Unsafe.InitBlockUnaligned(_buckets,0,(uint)(Unsafe.SizeOf<int>()*_bucketLength));
+            Unsafe.InitBlockUnaligned(_entries,0,(uint)(Unsafe.SizeOf<int>()*count));
+            _count = 0;
+            _freeList = -1;
+            _freeCount = 0;
+        }
+    }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool ContainsKey(T key)
+    {
+        return FindItemIndex(key) >= 0;
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool ContainsKeyRef(in T key)
+    {
+        return FindItemIndex(key) >= 0;
+    }
+
+    #endregion
+
+    
+    public void CopyTo(T[] array, int arrayIndex)
+    {
+        throw new NotImplementedException();
+    }
+    
+    public bool RemoveRef(in T key)
+    {
+        //if (_buckets == null) return false;
+        var entries = _entries;
+        Debug.Assert(entries != null, "entries should be non-null");
+
+        uint collisionCount = 0;
+        int last = -1;
+        int hashCode = key.GetHashCode();
+
+        ref int bucket = ref GetBucketRef(hashCode);
+        int i = bucket - 1; // Value in buckets is 1-based
+
+        while (i >= 0)
+        {
+            ref Entry entry = ref entries[i];
+
+            if (entry.HashCode == hashCode && (key.Equals(entry.Key)))
+            {
+                if (last < 0)
+                {
+                    bucket = entry.Next + 1; // Value in buckets is 1-based
+                }
+                else
+                {
+                    entries[last].Next = entry.Next;
+                }
+
+                Debug.Assert((StartOfFreeList - _freeList) < 0, "shouldn't underflow because max hashtable length is MaxPrimeArrayLength = 0x7FEFFFFD(2146435069) _freelist underflow threshold 2147483646");
+                entry.Next = StartOfFreeList - _freeList;
+
+                _freeList = i;
+                _freeCount++;
+                return true;
+            }
+
+            last = i;
+            i = entry.Next;
+
+            collisionCount++;
+            if (collisionCount > (uint)_entryLength)
+            {
+                // The chain of entries forms a loop; which means a concurrent update has happened.
+                // Break out of the loop and throw, rather than looping forever.
+                ThrowHelper.ConcurrentOperationsNotSupported();
+            }
+        }
+
+        return false;
+    }
+    
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool Remove(T item)
+    {
+        return RemoveRef(item);
+    }
+
+    public bool TryGetValue(in T key, out K actualValue)
+    {
+        int index = FindItemIndex(key);
+        if (index>=0)
+        {
+            actualValue = _entries[index].Value;
+            return true;
+        }
+        actualValue = default;
+        return false;
+    }
+
+    public int Count => _count - _freeCount;
+
+    public void Dispose()
+    {
+        NativeMemoryHelper.Free(_buckets);
+        NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<int>()*_bucketLength);
+        
+        NativeMemoryHelper.Free(_entries);
+        NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<Entry>()*_entryLength);
+    }
+    
+    #region Helper methods
+    
+    /// <summary>
+    /// Initializes buckets and slots arrays. Uses suggested capacity by finding next prime
+    /// greater than or equal to capacity.
+    /// </summary>
+    private int Initialize(int capacity)
+    {
+        int size = HashHelpers.GetPrime(capacity);
+        _buckets = (int*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<int>() * size));
+        _bucketLength = size;
+        _entries = (Entry*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<Entry>() * size));
+        _entryLength = size;
+        // Assign member variables after both arrays are allocated to guard against corruption from OOM if second fails.
+        _freeList = -1;
+        _freeCount = 0;
+        _count = 0;
+        _version = 0;
+#if TARGET_64BIT
+            _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)size);
+#endif
+
+        return size;
+    }
+    
+    
+    /// <summary>Adds the specified element to the set if it's not already contained.</summary>
+    /// <param name="value">The element to add to the set.</param>
+    /// <param name="location">The index into <see cref="_entries" /> of the element.</param>
+    /// <returns>true if the element is added to the <see cref="HashSet{T}" /> object; false if the element is already present.</returns>
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    private bool TryInsert(in T key,in K value,InsertionBehavior insertionBehavior)
+    {
+        //Console.WriteLine($"AddIfNotPresent:{value}");
+        //if (_buckets == null) Initialize(0);
+        Debug.Assert(_buckets != null);
+
+        Entry* entries = _entries;
+        Debug.Assert(entries != null, "expected entries to be non-null");
+
+        //var comparer = _comparer;
+        int hashCode;
+
+        uint collisionCount = 0;
+        ref var bucket = ref Unsafe.NullRef<int>();
+        
+        hashCode =  key.GetHashCode();
+        bucket = ref GetBucketRef(hashCode);
+        
+        var i = bucket - 1; // Value in _buckets is 1-based
+        // Console.WriteLine($"i:{i}");
+        while (i >= 0)
+        {
+            // Console.WriteLine($"i:{i}");
+            ref Entry entry = ref _entries[i];
+            // Console.WriteLine($"entry.HashCode:{entry.HashCode} hashCode:{hashCode} Equals:{comparer.Equals(entry.Value, value)}");
+            if (entry.HashCode == hashCode && entry.Key.Equals(key))
+            {
+                if (insertionBehavior== InsertionBehavior.OverwriteExisting)
+                {
+                    entries[i].Value = value;
+                    return true;
+                }
+                if (insertionBehavior == InsertionBehavior.ThrowOnExisting)
+                {
+                    ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException();
+                }
+
+                return false;
+            }
+
+            i = entry.Next;
+
+            collisionCount++;
+            // Console.WriteLine($"collisionCount :{collisionCount} i:{i}");
+            if (collisionCount > (uint)_entryLength)
+                // The chain of entries forms a loop, which means a concurrent update has happened.
+                ThrowHelper.ConcurrentOperationsNotSupported();
+        }
+        
+
+        int index;
+        if (_freeCount > 0)
+        {
+            index = _freeList;
+            _freeCount--;
+            Debug.Assert(StartOfFreeList - _entries[_freeList].Next >= -1,
+                "shouldn't overflow because `next` cannot underflow");
+            _freeList = StartOfFreeList - _entries[_freeList].Next;
+        }
+        else
+        {
+            var count = _count;
+            if (count == _entryLength)
+            {
+                Resize();
+                bucket = ref GetBucketRef(hashCode);
+            }
+
+            index = count;
+            _count = count + 1;
+        }
+
+        {
+            ref Entry entry = ref _entries[index];
+            entry.HashCode = hashCode;
+            entry.Next = bucket - 1; // Value in _buckets is 1-based
+            entry.Key = key;
+            entry.Value = value;
+            bucket = index + 1;
+            _version++;
+        }
+        
+        return true;
+    }
+        
+        /// <summary>Gets a reference to the specified hashcode's bucket, containing an index into <see cref="_entries"/>.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private ref int GetBucketRef(int hashCode)
+        {
+            //var buckets = _buckets;
+            
+#if TARGET_64BIT
+            return ref _buckets[HashHelpers.FastMod((uint)hashCode, (uint)_buckets.Length, _fastModMultiplier)];
+#else
+            int index = (int)((uint)hashCode %(uint)_bucketLength);
+            return ref _buckets[index];
+#endif
+        }
+
+    #endregion
+
+    
+
+            /// <summary>Ensures that this hash set can hold the specified number of elements without growing.</summary>
+        public int EnsureCapacity(int capacity)
+        {
+            if (capacity < 0)
+            {
+                ThrowHelper.HashSetCapacityOutOfRange();
+            }
+
+            int currentCapacity = _entries == null ? 0 : _entryLength;
+            if (currentCapacity >= capacity)
+            {
+                return currentCapacity;
+            }
+
+            if (_buckets == null)
+            {
+                return Initialize(capacity);
+            }
+
+            int newSize = HashHelpers.GetPrime(capacity);
+            Resize(newSize, forceNewHashCodes: false);
+            return newSize;
+        }
+
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private void Resize() => Resize(HashHelpers.ExpandPrime(_count), forceNewHashCodes: false);
+
+        private void Resize(int newSize, bool forceNewHashCodes)
+        {
+            // Console.WriteLine($"before resize:{*self}");
+            // Value types never rehash
+            Debug.Assert(!forceNewHashCodes || !typeof(T).IsValueType);
+            Debug.Assert(_entries != null, "_entries should be non-null");
+            Debug.Assert(newSize >= _entryLength);
+            // Console.WriteLine($"Resize newSize:{newSize} byteSize:{Unsafe.SizeOf<Entry>() * newSize}");
+            var newEntries = (Entry*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<Entry>() * newSize));
+            Unsafe.CopyBlockUnaligned(newEntries,_entries,(uint)(Unsafe.SizeOf<Entry>()*_entryLength));
+            int count = _count;
+            // Assign member variables after both arrays allocated to guard against corruption from OOM if second fails
+            var newBucket = (int*)NativeMemoryHelper.AllocZeroed((UIntPtr)(Unsafe.SizeOf<int>() * newSize));
+            NativeMemoryHelper.Free(_buckets);
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<int>()*_bucketLength);
+            _buckets = newBucket;
+            _bucketLength = newSize;
+#if TARGET_64BIT
+            _fastModMultiplier = HashHelpers.GetFastModMultiplier((uint)newSize);
+#endif
+            for (int i = 0; i < count; i++)
+            {
+                ref Entry entry = ref newEntries[i];
+                if (entry.Next >= -1)
+                {
+                    ref int bucket = ref GetBucketRef(entry.HashCode);
+                    entry.Next = bucket - 1; // Value in _buckets is 1-based
+                    // Console.WriteLine($"entry.Next:{entry.Next} bucket:{bucket}");
+                    bucket = i + 1;
+                }
+            }
+            NativeMemoryHelper.Free(_entries);
+            NativeMemoryHelper.RemoveNativeMemoryByte(Unsafe.SizeOf<Entry>()*_entryLength);
+            _entries = newEntries;
+            _entryLength = newSize;
+            
+            //Console.WriteLine($"after resize:{*self} totalSize:{_entryLength}");
+        }
+        
+        /// <summary>Gets the index of the item in <see cref="_entries"/>, or -1 if it's not in the set.</summary>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private int FindItemIndex(in T key)
+        {
+            //if (_buckets == null) return -1;
+            var entries = _entries;
+            Debug.Assert(entries != null, "Expected _entries to be initialized");
+
+            uint collisionCount = 0;
+            //IEqualityComparer<T>? comparer = _comparer;
+            
+            int hashCode = key.GetHashCode();
+            int i = GetBucketRef(hashCode) - 1; // Value in _buckets is 1-based
+            while (i >= 0)
+            {
+                ref Entry entry = ref entries[i];
+                if (entry.HashCode == hashCode && key.Equals(entry.Key))
+                {
+                    return i;
+                }
+                i = entry.Next;
+
+                collisionCount++;
+                if (collisionCount > (uint)_entryLength)
+                {
+                    // The chain of entries forms a loop, which means a concurrent update has happened.
+                    ThrowHelper.ConcurrentOperationsNotSupported();
+                }
+            }
+
+            return -1;
+        }
+
+    
+    private struct Entry : IEquatable<Entry>
+    {
+        public int HashCode;
+
+        /// <summary>
+        /// 0-based index of next entry in chain: -1 means end of chain
+        /// also encodes whether this entry _itself_ is part of the free list by changing sign and subtracting 3,
+        /// so -2 means end of free list, -3 means index 0 but on free list, -4 means index 1 but on free list, etc.
+        /// </summary>
+        public int Next;
+        public T Key;
+        public K Value;
+        public bool Equals(Entry other)
+        {
+            return HashCode == other.HashCode && Next == other.Next && Key.Equals(other.Key);
+        }
+    }
+
+    public override string ToString()
+    {
+        StringBuilder sb = new StringBuilder();
+        foreach (var value in *_self)
+        {
+            sb.Append($"{value} ");
+        }
+
+        sb.Append("\n");
+        return sb.ToString();
+    }
+    
+    internal enum InsertionBehavior : byte
+    {
+        None,
+        OverwriteExisting,
+        ThrowOnExisting,
+    }
+
+    public struct Enumerator : IEnumerator<MapPair<T, K>>
+    {
+        private readonly UnOrderMap<T,K>* _unOrderMap;
+        private readonly int _version;
+        private int _index;
+        private MapPair<T, K> _current;
+
+        internal Enumerator(UnOrderMap<T,K>* unOrderMap)
+        {
+            _unOrderMap = unOrderMap;
+            _version = unOrderMap->_version;
+            _index = 0;
+            _current = default!;
+        }
+
+        public bool MoveNext()
+        {
+            if (_version != _unOrderMap->_version)
+                ThrowHelper.HashSetEnumFailedVersion();
+            
+            // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
+            // dictionary.count+1 could be negative if dictionary.count is int.MaxValue
+            while ((uint)_index < (uint)_unOrderMap->_count)
+            {
+                ref Entry entry = ref _unOrderMap->_entries[_index++];
+                if (entry.Next >= -1)
+                {
+                    _current = new MapPair<T, K>(entry.Key,entry.Value);
+                    return true;
+                }
+            }
+
+            _index = _unOrderMap->_count + 1;
+            _current = default!;
+            return false;
+        }
+
+        public MapPair<T, K> Current => _current;
+
+        public void Dispose()
+        {
+        }
+        
+        object IEnumerator.Current => Current;
+        
+        public void Reset()
+        {
+            if (_version != _unOrderMap->_version)
+                ThrowHelper.HashSetEnumFailedVersion();
+
+            _index = 0;
+            _current = default!;
+        }
+    }
+}
+}
+

+ 11 - 0
Unity/Assets/Scripts/ThirdParty/NativeCollection/UnsafeType/UnOrderMap/UnOrderMap.cs.meta

@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dd8571bdfd2ae9e409e54e042b6d87f2
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: