A game about forced loneliness, made by TACStudios
1using System;
2using Unity.Collections.LowLevel.Unsafe;
3
4namespace Unity.Collections
5{
6 /// <summary>
7 /// Provides extension methods for hash maps.
8 /// </summary>
9 [GenerateTestsForBurstCompatibility]
10 public static class NativeParallelHashMapExtensions
11 {
12 /// <summary>
13 /// Removes duplicate values from this sorted array and returns the number of values remaining.
14 /// </summary>
15 /// <remarks>
16 /// Uses `Equals` to determine whether values are duplicates.
17 ///
18 /// Expects the array to already be sorted.
19 ///
20 /// The remaining elements will be tightly packed at the front of the array.
21 /// </remarks>
22 /// <typeparam name="T">The type of values in the array.</typeparam>
23 /// <param name="array">The array from which to remove duplicates.</param>
24 /// <returns>The number of unique elements in this array.</returns>
25 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int) })]
26 public static int Unique<T>(this NativeArray<T> array)
27 where T : unmanaged, IEquatable<T>
28 {
29 if (array.Length == 0)
30 {
31 return 0;
32 }
33
34 int first = 0;
35 int last = array.Length;
36 var result = first;
37 while (++first != last)
38 {
39 if (!array[result].Equals(array[first]))
40 {
41 array[++result] = array[first];
42 }
43 }
44
45 return ++result;
46 }
47
48 /// <summary>
49 /// Returns an array populated with the unique keys from this multi hash map.
50 /// </summary>
51 /// <typeparam name="TKey">The type of the keys.</typeparam>
52 /// <typeparam name="TValue">The type of the values.</typeparam>
53 /// <param name="container">The multi hash map.</param>
54 /// <param name="allocator">The allocator to use.</param>
55 /// <returns>An array populated with the unique keys from this multi hash map.</returns>
56 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
57 public static (NativeArray<TKey>, int) GetUniqueKeyArray<TKey, TValue>(this UnsafeParallelMultiHashMap<TKey, TValue> container, AllocatorManager.AllocatorHandle allocator)
58 where TKey : unmanaged, IEquatable<TKey>, IComparable<TKey>
59 where TValue : unmanaged
60 {
61 var result = container.GetKeyArray(allocator);
62 result.Sort();
63 int uniques = result.Unique();
64 return (result, uniques);
65 }
66
67 /// <summary>
68 /// Returns an array populated with the unique keys from this multi hash map.
69 /// </summary>
70 /// <typeparam name="TKey">The type of the keys.</typeparam>
71 /// <typeparam name="TValue">The type of the values.</typeparam>
72 /// <param name="container">The multi hash map.</param>
73 /// <param name="allocator">The allocator to use.</param>
74 /// <returns>An array populated with the unique keys from this multi hash map.</returns>
75 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
76 public static (NativeArray<TKey>, int) GetUniqueKeyArray<TKey, TValue>(this NativeParallelMultiHashMap<TKey, TValue> container, AllocatorManager.AllocatorHandle allocator)
77 where TKey : unmanaged, IEquatable<TKey>, IComparable<TKey>
78 where TValue : unmanaged
79 {
80 var result = container.GetKeyArray(allocator);
81 result.Sort();
82 int uniques = result.Unique();
83 return (result, uniques);
84 }
85
86 /// <summary>
87 /// Returns a "bucket" view of this hash map.
88 /// </summary>
89 /// <remarks>
90 /// Internally, the elements of a hash map are split into buckets of type <see cref="UnsafeParallelHashMapBucketData"/>.
91 ///
92 /// With buckets, a job can safely access the elements of a hash map concurrently as long as each individual bucket is accessed
93 /// only from an individual thread. Effectively, it is not safe to read elements of an individual bucket concurrently,
94 /// but it is safe to read elements of separate buckets concurrently.
95 /// </remarks>
96 /// <typeparam name="TKey">The type of the keys.</typeparam>
97 /// <typeparam name="TValue">The type of the values.</typeparam>
98 /// <param name="container">The hash map.</param>
99 /// <returns>A "bucket" view of this hash map.</returns>
100 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new[] { typeof(int), typeof(int) })]
101 public static unsafe UnsafeParallelHashMapBucketData GetUnsafeBucketData<TKey, TValue>(this NativeParallelHashMap<TKey, TValue> container)
102 where TKey : unmanaged, IEquatable<TKey>
103 where TValue : unmanaged
104 {
105 return container.m_HashMapData.m_Buffer->GetBucketData();
106 }
107
108 /// <summary>
109 /// Returns a "bucket" view of this multi hash map.
110 /// </summary>
111 /// <remarks>
112 /// Internally, the elements of a hash map are split into buckets of type <see cref="UnsafeParallelHashMapBucketData"/>.
113 ///
114 /// With buckets, a job can safely access the elements of a hash map concurrently as long as each individual bucket is accessed
115 /// only from an individual thread. Effectively, it is not safe to read elements of an individual bucket concurrently,
116 /// but it is safe to read elements of separate buckets concurrently.
117 /// </remarks>
118 /// <typeparam name="TKey">The type of the keys.</typeparam>
119 /// <typeparam name="TValue">The type of the values.</typeparam>
120 /// <param name="container">The multi hash map.</param>
121 /// <returns>A "bucket" view of this multi hash map.</returns>
122 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
123 public static unsafe UnsafeParallelHashMapBucketData GetUnsafeBucketData<TKey, TValue>(this NativeParallelMultiHashMap<TKey, TValue> container)
124 where TKey : unmanaged, IEquatable<TKey>
125 where TValue : unmanaged
126 {
127 return container.m_MultiHashMapData.m_Buffer->GetBucketData();
128 }
129
130 /// <summary>
131 /// Removes all occurrences of a particular key-value pair.
132 /// </summary>
133 /// <remarks>Removes all key-value pairs which have a particular key and which *also have* a particular value.
134 /// In other words: (key *AND* value) rather than (key *OR* value).</remarks>
135 /// <typeparam name="TKey">The type of the keys.</typeparam>
136 /// <typeparam name="TValue">The type of the values.</typeparam>
137 /// <param name="container">The multi hash map.</param>
138 /// <param name="key">The key of the key-value pairs to remove.</param>
139 /// <param name="value">The value of the key-value pairs to remove.</param>
140 [GenerateTestsForBurstCompatibility(GenericTypeArguments = new [] { typeof(int), typeof(int) })]
141 public static void Remove<TKey, TValue>(this NativeParallelMultiHashMap<TKey, TValue> container, TKey key, TValue value)
142 where TKey : unmanaged, IEquatable<TKey>
143 where TValue : unmanaged, IEquatable<TValue>
144 {
145#if ENABLE_UNITY_COLLECTIONS_CHECKS
146 AtomicSafetyHandle.CheckWriteAndBumpSecondaryVersion(container.m_Safety);
147#endif
148 container.m_MultiHashMapData.Remove(key, value);
149 }
150 }
151}