152 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			152 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using Unity.Collections.LowLevel.Unsafe; | ||
|  | 
 | ||
|  | namespace Unity.Collections | ||
|  | { | ||
|  |     /// <summary> | ||
|  |     /// Provides extension methods for hash maps. | ||
|  |     /// </summary> | ||
|  |     [GenerateTestsForBurstCompatibility] | ||
|  |     public static class NativeParallelHashMapExtensions | ||
|  |     { | ||
|  |         /// <summary> | ||
|  |         /// Removes duplicate values from this sorted array and returns the number of values remaining. | ||
|  |         /// </summary> | ||
|  |         /// <remarks> | ||
|  |         /// Uses `Equals` to determine whether values are duplicates. | ||
|  |         /// | ||
|  |         /// Expects the array to already be sorted. | ||
|  |         /// | ||
|  |         /// The remaining elements will be tightly packed at the front of the array. | ||
|  |         /// </remarks> | ||
|  |         /// <typeparam name="T">The type of values in the array.</typeparam> | ||
|  |         /// <param name="array">The array from which to remove duplicates.</param> | ||
|  |         /// <returns>The number of unique elements in this array.</returns> | ||
|  |         [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })] | ||
|  |         public static int Unique<T>(this NativeArray<T> array) | ||
|  |             where T : unmanaged, IEquatable<T> | ||
|  |         { | ||
|  |             if (array.Length == 0) | ||
|  |             { | ||
|  |                 return 0; | ||
|  |             } | ||
|  | 
 | ||
|  |             int first = 0; | ||
|  |             int last = array.Length; | ||
|  |             var result = first; | ||
|  |             while (++first != last) | ||
|  |             { | ||
|  |                 if (!array[result].Equals(array[first])) | ||
|  |                 { | ||
|  |                     array[++result] = array[first]; | ||
|  |                 } | ||
|  |             } | ||
|  | 
 | ||
|  |             return ++result; | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Returns an array populated with the unique keys from this multi hash map. | ||
|  |         /// </summary> | ||
|  |         /// <typeparam name="TKey">The type of the keys.</typeparam> | ||
|  |         /// <typeparam name="TValue">The type of the values.</typeparam> | ||
|  |         /// <param name="container">The multi hash map.</param> | ||
|  |         /// <param name="allocator">The allocator to use.</param> | ||
|  |         /// <returns>An array populated with the unique keys from this multi hash map.</returns> | ||
|  |         [GenerateTestsForBurstCompatibility(GenericTypeArguments = new[] { typeof(int), typeof(int) })] | ||
|  |         public static (NativeArray<TKey>, int) GetUniqueKeyArray<TKey, TValue>(this UnsafeParallelMultiHashMap<TKey, TValue> container, AllocatorManager.AllocatorHandle allocator) | ||
|  |             where TKey : unmanaged, IEquatable<TKey>, IComparable<TKey> | ||
|  |             where TValue : unmanaged | ||
|  |         { | ||
|  |             var result = container.GetKeyArray(allocator); | ||
|  |             result.Sort(); | ||
|  |             int uniques = result.Unique(); | ||
|  |             return (result, uniques); | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Returns an array populated with the unique keys from this multi hash map. | ||
|  |         /// </summary> | ||
|  |         /// <typeparam name="TKey">The type of the keys.</typeparam> | ||
|  |         /// <typeparam name="TValue">The type of the values.</typeparam> | ||
|  |         /// <param name="container">The multi hash map.</param> | ||
|  |         /// <param name="allocator">The allocator to use.</param> | ||
|  |         /// <returns>An array populated with the unique keys from this multi hash map.</returns> | ||
|  |         [GenerateTestsForBurstCompatibility(GenericTypeArguments = new[] { typeof(int), typeof(int) })] | ||
|  |         public static (NativeArray<TKey>, int) GetUniqueKeyArray<TKey, TValue>(this NativeParallelMultiHashMap<TKey, TValue> container, AllocatorManager.AllocatorHandle allocator) | ||
|  |             where TKey : unmanaged, IEquatable<TKey>, IComparable<TKey> | ||
|  |             where TValue : unmanaged | ||
|  |         { | ||
|  |             var result = container.GetKeyArray(allocator); | ||
|  |             result.Sort(); | ||
|  |             int uniques = result.Unique(); | ||
|  |             return (result, uniques); | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Returns a "bucket" view of this hash map. | ||
|  |         /// </summary> | ||
|  |         /// <remarks> | ||
|  |         /// Internally, the elements of a hash map are split into buckets of type <see cref="UnsafeParallelHashMapBucketData"/>. | ||
|  |         /// | ||
|  |         /// With buckets, a job can safely access the elements of a hash map concurrently as long as each individual bucket is accessed | ||
|  |         /// only from an individual thread. Effectively, it is not safe to read elements of an individual bucket concurrently, | ||
|  |         /// but it is safe to read elements of separate buckets concurrently. | ||
|  |         /// </remarks> | ||
|  |         /// <typeparam name="TKey">The type of the keys.</typeparam> | ||
|  |         /// <typeparam name="TValue">The type of the values.</typeparam> | ||
|  |         /// <param name="container">The hash map.</param> | ||
|  |         /// <returns>A "bucket" view of this hash map.</returns> | ||
|  |         [GenerateTestsForBurstCompatibility(GenericTypeArguments = new[] { typeof(int), typeof(int) })] | ||
|  |         public static unsafe UnsafeParallelHashMapBucketData GetUnsafeBucketData<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> container) | ||
|  |             where TKey : unmanaged, IEquatable<TKey> | ||
|  |             where TValue : unmanaged | ||
|  |         { | ||
|  |             return container.m_HashMapData.m_Buffer->GetBucketData(); | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Returns a "bucket" view of this multi hash map. | ||
|  |         /// </summary> | ||
|  |         /// <remarks> | ||
|  |         /// Internally, the elements of a hash map are split into buckets of type <see cref="UnsafeParallelHashMapBucketData"/>. | ||
|  |         /// | ||
|  |         /// With buckets, a job can safely access the elements of a hash map concurrently as long as each individual bucket is accessed | ||
|  |         /// only from an individual thread. Effectively, it is not safe to read elements of an individual bucket concurrently, | ||
|  |         /// but it is safe to read elements of separate buckets concurrently. | ||
|  |         /// </remarks> | ||
|  |         /// <typeparam name="TKey">The type of the keys.</typeparam> | ||
|  |         /// <typeparam name="TValue">The type of the values.</typeparam> | ||
|  |         /// <param name="container">The multi hash map.</param> | ||
|  |         /// <returns>A "bucket" view of this multi hash map.</returns> | ||
|  |         [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] | ||
|  |         public static unsafe UnsafeParallelHashMapBucketData GetUnsafeBucketData<TKey, TValue>(this NativeParallelMultiHashMap<TKey, TValue> container) | ||
|  |             where TKey : unmanaged, IEquatable<TKey> | ||
|  |             where TValue : unmanaged | ||
|  |         { | ||
|  |             return container.m_MultiHashMapData.m_Buffer->GetBucketData(); | ||
|  |         } | ||
|  | 
 | ||
|  |         /// <summary> | ||
|  |         /// Removes all occurrences of a particular key-value pair. | ||
|  |         /// </summary> | ||
|  |         /// <remarks>Removes all key-value pairs which have a particular key and which *also have* a particular value. | ||
|  |         /// In other words: (key *AND* value) rather than (key *OR* value).</remarks> | ||
|  |         /// <typeparam name="TKey">The type of the keys.</typeparam> | ||
|  |         /// <typeparam name="TValue">The type of the values.</typeparam> | ||
|  |         /// <param name="container">The multi hash map.</param> | ||
|  |         /// <param name="key">The key of the key-value pairs to remove.</param> | ||
|  |         /// <param name="value">The value of the key-value pairs to remove.</param> | ||
|  |         [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })] | ||
|  |         public static void Remove<TKey, TValue>(this NativeParallelMultiHashMap<TKey, TValue> container, TKey key, TValue value) | ||
|  |             where TKey : unmanaged, IEquatable<TKey> | ||
|  |             where TValue : unmanaged, IEquatable<TValue> | ||
|  |         { | ||
|  | #if ENABLE_UNITY_COLLECTIONS_CHECKS | ||
|  |             AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(container.m_Safety); | ||
|  | #endif | ||
|  |             container.m_MultiHashMapData.Remove(key, value); | ||
|  |         } | ||
|  |     } | ||
|  | } |