< Summary

Class:GDX.Collections.UnsafeSparseSet
Assembly:GDX
File(s):D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/Collections/UnsafeSparseSet.cs
Covered lines:558
Uncovered lines:2
Coverable lines:560
Total lines:1046
Line coverage:99.6% (558 of 560)
Covered branches:0
Total branches:0
Covered methods:32
Total methods:32
Method coverage:100% (32 of 32)

Coverage History

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
UnsafeSparseSet(...)0%440100%
UnsafeSparseSet(...)0%440100%
AddWithExpandCheck(...)0%660100%
AddWithExpandCheck(...)0%770100%
AddUnchecked(...)0%110100%
AddUnchecked(...)0%110100%
GetDenseIndexUnchecked(...)0%110100%
GetDenseIndexWithBoundsCheck(...)0%6.016092.86%
GetDenseIndexWithVersionCheck(...)0%220100%
GetDenseIndexWithBoundsAndVersionCheck(...)0%7.017093.33%
RemoveWithBoundsCheck(...)0%770100%
RemoveWithBoundsAndVersionChecks(...)0%880100%
RemoveUnchecked(...)0%110100%
RemoveUnchecked(...)0%110100%
RemoveUnchecked(...)0%110100%
RemoveUnchecked(...)0%110100%
RemoveUncheckedFromDenseIndex(...)0%110100%
RemoveUncheckedFromDenseIndex(...)0%110100%
RemoveUncheckedFromDenseIndex(...)0%110100%
RemoveUncheckedFromDenseIndex(...)0%110100%
RemoveWithVersionCheck(...)0%220100%
Clear()0%220100%
Clear(...)0%220100%
ClearWithVersionArrayReset(...)0%220100%
Expand(...)0%550100%
Expand(...)0%660100%
Reserve(...)0%660100%
Reserve(...)0%770100%
Dispose()0%220100%
DisposeVersionArray(...)0%110100%

File(s)

D:/BuildAgent/work/GDX-Documentation/Projects/GDX_Development/Packages/com.dotbunny.gdx/GDX/Collections/UnsafeSparseSet.cs

#LineLine coverage
 1// Copyright (c) 2020-2022 dotBunny Inc.
 2// dotBunny licenses this file to you under the BSL-1.0 license.
 3// See the LICENSE file in the project root for more information.
 4
 5using System.Runtime.CompilerServices;
 6using Unity.Collections;
 7using Unity.Collections.LowLevel.Unsafe;
 8using Unity.Jobs.LowLevel.Unsafe;
 9
 10namespace GDX.Collections
 11{
 12    /// <summary>
 13    ///     An adapter collection for external data arrays that allows constant-time insertion, deletion, and lookup by
 14    ///     handle, as well as array-like iteration.
 15    /// </summary>
 16    public unsafe struct UnsafeSparseSet : System.IDisposable
 17    {
 18        public const int MinimumCapacity = JobsUtility.CacheLineSize / (sizeof(int) * 2);
 19
 20        public void* Data;
 21        /// <summary>
 22        ///     Holds references to the sparse array for swapping indices.
 23        /// </summary>
 24        public int* DenseArray
 25        {
 26            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 39827            get => (int*)Data + Length;
 28        }
 29
 30        /// <summary>
 31        ///     Holds references to dense array indices.
 32        /// </summary>
 33        /// <remarks>
 34        ///     Its own indices are claimed and freed via a free-list.
 35        /// </remarks>
 36        public int* SparseArray
 37        {
 38            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 46039            get => (int*)Data;
 40        }
 41
 42        /// <summary>
 43        ///     How many indices are being used currently?
 44        /// </summary>
 45        public int Count;
 46
 47        /// <summary>
 48        ///     The first free (currently unused) index in the sparse array.
 49        /// </summary>
 50        public int FreeIndex;
 51
 52        /// <summary>
 53        ///     The current capacity of both the sparse and dense arrays.
 54        /// </summary>
 55        public int Length;
 56
 57        public AllocatorManager.AllocatorHandle Allocator;
 58
 59        /// <summary>
 60        ///     Create a <see cref="NativeArraySparseSet" /> with an <paramref name="initialCapacity" />.
 61        /// </summary>
 62        /// <param name="initialCapacity">The initial capacity of the sparse and dense int arrays.</param>
 63        /// <param name="allocator">The <see cref="AllocatorManager.AllocatorHandle" /> type to use.</param>
 64        public UnsafeSparseSet(int initialCapacity, AllocatorManager.AllocatorHandle allocator)
 1465        {
 1466            initialCapacity = initialCapacity > MinimumCapacity ? initialCapacity : MinimumCapacity;
 1467            --initialCapacity;
 1468            initialCapacity |= initialCapacity >> 1;
 1469            initialCapacity |= initialCapacity >> 2;
 1470            initialCapacity |= initialCapacity >> 4;
 1471            initialCapacity |= initialCapacity >> 8;
 1472            initialCapacity |= initialCapacity >> 16;
 1473            ++initialCapacity;
 74
 1475            Data = allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, initialCapacity * 2);
 1476            Count = 0;
 1477            FreeIndex = 0;
 1478            Length = initialCapacity;
 1479            Allocator = allocator;
 80
 25281            for (int i = 0; i < initialCapacity; i++)
 11282            {
 11283                DenseArray[i] = -1;
 11284                SparseArray[i] = i + 1;
 11285            }
 1486        }
 87
 88        /// <summary>
 89        ///     Create a <see cref="NativeArraySparseSet" /> with an <paramref name="initialCapacity" />.
 90        /// </summary>
 91        /// <param name="initialCapacity">The initial capacity of the sparse and dense int arrays.</param>
 92        /// <param name="allocator">The <see cref="Unity.Collections.Allocator" /> type to use.</param>
 93        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 94        public UnsafeSparseSet(int initialCapacity, AllocatorManager.AllocatorHandle allocator, out ulong* versionArray)
 1695        {
 1696            initialCapacity = initialCapacity > MinimumCapacity ? initialCapacity : MinimumCapacity;
 1697            --initialCapacity;
 1698            initialCapacity |= initialCapacity >> 1;
 1699            initialCapacity |= initialCapacity >> 2;
 16100            initialCapacity |= initialCapacity >> 4;
 16101            initialCapacity |= initialCapacity >> 8;
 16102            initialCapacity |= initialCapacity >> 16;
 16103            ++initialCapacity;
 104
 16105            Data = allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, initialCapacity * 2);
 16106            Count = 0;
 16107            FreeIndex = 0;
 16108            Length = initialCapacity;
 16109            Allocator = allocator;
 16110            versionArray = (ulong*)allocator.Allocate(sizeof(ulong), JobsUtility.CacheLineSize, initialCapacity);
 111
 288112            for (int i = 0; i < initialCapacity; i++)
 128113            {
 128114                DenseArray[i] = -1;
 128115                SparseArray[i] = i + 1;
 128116                versionArray[i] = 1;
 128117            }
 16118        }
 119
 120        /// <summary>
 121        ///     Adds a sparse/dense index pair to the set and expands the arrays if necessary.
 122        /// </summary>
 123        /// <param name="expandBy">How many indices to expand by.</param>
 124        /// <param name="sparseIndex">The sparse index allocated.</param>
 125        /// <param name="denseIndex">The dense index allocated.</param>
 126        /// <returns>True if the index pool expanded.</returns>
 127        public bool AddWithExpandCheck(int expandBy, out int sparseIndex, out int denseIndex)
 18128        {
 18129            int indexToClaim = FreeIndex;
 18130            int currentCapacity = Length;
 18131            bool needsExpansion = false;
 132
 18133            if (indexToClaim >= currentCapacity)
 2134            {
 135                // We're out of space, the last free index points to nothing. Allocate more indices.
 2136                needsExpansion = true;
 137
 2138                int newCapacity = currentCapacity + expandBy;
 139
 2140                newCapacity = newCapacity > MinimumCapacity ? newCapacity : MinimumCapacity;
 2141                --newCapacity;
 2142                newCapacity |= newCapacity >> 1;
 2143                newCapacity |= newCapacity >> 2;
 2144                newCapacity |= newCapacity >> 4;
 2145                newCapacity |= newCapacity >> 8;
 2146                newCapacity |= newCapacity >> 16;
 2147                ++newCapacity;
 148
 2149                void* newData = Allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, newCapacity * 2);
 150
 2151                UnsafeUtility.MemCpy(newData, Data, sizeof(int) * currentCapacity);
 2152                int* newSparseArray = (int*)newData;
 36153                for (int i = currentCapacity; i < newCapacity; i++)
 16154                {
 16155                    newSparseArray[i] = i + 1;
 16156                }
 157
 2158                int* newDenseArray = newSparseArray + newCapacity;
 2159                UnsafeUtility.MemCpy(newDenseArray, DenseArray, sizeof(int) * currentCapacity);
 36160                for (int i = currentCapacity; i < newCapacity; i++)
 16161                {
 16162                    newDenseArray[i] = -1;
 16163                }
 164
 2165                Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, currentCapacity * 2);
 166
 2167                Data = newData;
 2168                Length = newCapacity;
 2169            }
 170
 18171            int nextFreeIndex = SparseArray[indexToClaim];
 18172            DenseArray[Count] = indexToClaim; // Point the next dense id at our newly claimed sparse index.
 18173            SparseArray[indexToClaim] = Count; // Point our newly claimed sparse index at the dense index.
 18174            denseIndex = Count;
 175
 18176            ++Count;
 18177            FreeIndex = nextFreeIndex; // Set the free list head for next time.
 178
 18179            sparseIndex = indexToClaim;
 18180            return needsExpansion;
 18181        }
 182
 183        /// <summary>
 184        ///     Adds a sparse/dense index pair to the set and expands the arrays if necessary.
 185        /// </summary>
 186        /// <param name="expandBy">How many indices to expand by.</param>
 187        /// <param name="sparseIndex">The sparse index allocated.</param>
 188        /// <param name="denseIndex">The dense index allocated.</param>
 189        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 190        /// <returns>True if the index pool expanded.</returns>
 191        public bool AddWithExpandCheck(int expandBy, out int sparseIndex, out int denseIndex, ref ulong* versionArray)
 9192        {
 9193            int indexToClaim = FreeIndex;
 9194            int currentCapacity = Length;
 9195            bool needsExpansion = false;
 196
 9197            if (indexToClaim >= currentCapacity)
 1198            {
 199                // We're out of space, the last free index points to nothing. Allocate more indices.
 1200                needsExpansion = true;
 201
 1202                int newCapacity = currentCapacity + expandBy;
 203
 1204                newCapacity = newCapacity > MinimumCapacity ? newCapacity : MinimumCapacity;
 1205                --newCapacity;
 1206                newCapacity |= newCapacity >> 1;
 1207                newCapacity |= newCapacity >> 2;
 1208                newCapacity |= newCapacity >> 4;
 1209                newCapacity |= newCapacity >> 8;
 1210                newCapacity |= newCapacity >> 16;
 1211                ++newCapacity;
 212
 1213                void* newData = Allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, newCapacity * 2);
 214
 1215                UnsafeUtility.MemCpy(newData, Data, sizeof(int) * currentCapacity);
 1216                int* newSparseArray = (int*)newData;
 18217                for (int i = currentCapacity; i < newCapacity; i++)
 8218                {
 8219                    newSparseArray[i] = i + 1;
 8220                }
 221
 1222                int* newDenseArray = newSparseArray + newCapacity;
 1223                UnsafeUtility.MemCpy(newDenseArray, DenseArray, sizeof(int) * currentCapacity);
 18224                for (int i = currentCapacity; i < newCapacity; i++)
 8225                {
 8226                    newDenseArray[i] = -1;
 8227                }
 228
 1229                ulong* newVersionArray = (ulong*)Allocator.Allocate(sizeof(ulong), JobsUtility.CacheLineSize, currentCap
 1230                UnsafeUtility.MemCpy(newVersionArray, versionArray, sizeof(ulong) * currentCapacity);
 18231                for (int i = currentCapacity; i < newCapacity; i++)
 8232                {
 8233                    newVersionArray[i] = 1;
 8234                }
 235
 1236                Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, currentCapacity * 2);
 1237                Allocator.Free(versionArray, sizeof(ulong), JobsUtility.CacheLineSize, currentCapacity);
 1238                versionArray = newVersionArray;
 239
 1240                Data = newData;
 1241                Length = newCapacity;
 1242            }
 243
 9244            int nextFreeIndex = SparseArray[indexToClaim];
 9245            DenseArray[Count] = indexToClaim; // Point the next dense id at our newly claimed sparse index.
 9246            SparseArray[indexToClaim] = Count; // Point our newly claimed sparse index at the dense index.
 9247            denseIndex = Count;
 248
 9249            ++Count;
 9250            FreeIndex = nextFreeIndex; // Set the free list head for next time.
 251
 9252            sparseIndex = indexToClaim;
 9253            return needsExpansion;
 9254        }
 255
 256        /// <summary>
 257        ///     Adds a sparse/dense index pair to the set without checking if the set needs to expand.
 258        /// </summary>
 259        /// <param name="sparseIndex">The sparse index allocated.</param>
 260        /// <param name="denseIndex">The dense index allocated.</param>
 261        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 262        public void AddUnchecked(out int sparseIndex, out int denseIndex)
 18263        {
 18264            int indexToClaim = FreeIndex;
 18265            int nextFreeIndex = SparseArray[indexToClaim];
 18266            DenseArray[Count] = indexToClaim; // Point the next dense id at our newly claimed sparse index.
 18267            SparseArray[indexToClaim] = Count; // Point our newly claimed sparse index at the dense index.
 268
 18269            sparseIndex = indexToClaim;
 18270            denseIndex = Count;
 18271            ++Count;
 18272            FreeIndex = nextFreeIndex; // Set the free list head for next time.
 18273        }
 274
 275        /// <summary>
 276        ///     Adds a sparse/dense index pair to the set without checking if the set needs to expand.
 277        /// </summary>
 278        /// <param name="sparseIndex">The sparse index allocated.</param>
 279        /// <param name="denseIndex">The dense index allocated.</param>
 280        /// <param name="versionArray">The array containing the version number to check against.</param>
 281        /// <param name="version">Enables detection of use-after-free errors when using the sparse index as a reference.
 282        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 283        public void AddUnchecked(out int sparseIndex, out int denseIndex, ulong* versionArray, out ulong version)
 22284        {
 22285            int indexToClaim = FreeIndex;
 22286            int nextFreeIndex = SparseArray[indexToClaim];
 22287            DenseArray[Count] = indexToClaim; // Point the next dense id at our newly claimed sparse index.
 22288            SparseArray[indexToClaim] = Count; // Point our newly claimed sparse index at the dense index.
 289
 22290            version = versionArray[indexToClaim];
 22291            sparseIndex = indexToClaim;
 22292            denseIndex = Count;
 293
 22294            ++Count;
 22295            FreeIndex = nextFreeIndex; // Set the free list head for next time.
 22296        }
 297
 298        /// <summary>
 299        ///     Gets the value of the sparse array at the given index without any data validation.
 300        /// </summary>
 301        /// <param name="sparseIndex">The index to check in the sparse array.</param>
 302        /// <returns>The dense index at the given sparse index.</returns>
 303        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 304        public int GetDenseIndexUnchecked(int sparseIndex)
 1305        {
 1306            return SparseArray[sparseIndex];
 1307        }
 308
 309        /// <summary>
 310        ///     Gets the value of the sparse array at the given index,
 311        ///     or -1 if the dense and sparse indices don't point to each other or if the dense index is outside the den
 312        /// </summary>
 313        /// <param name="sparseIndex">The index in the sparse array to check against.</param>
 314        /// <returns>The dense index pointed to by the current sparse index, or -1 if invalid.</returns>
 315        public int GetDenseIndexWithBoundsCheck(int sparseIndex)
 4316        {
 4317            if (sparseIndex >= 0 && sparseIndex < Length)
 3318            {
 3319                int denseIndex = SparseArray[sparseIndex];
 320
 3321                if (denseIndex < Count && denseIndex >= 0)
 1322                {
 1323                    int sparseIndexAtDenseIndex = DenseArray[denseIndex];
 324
 1325                    if (sparseIndex == sparseIndexAtDenseIndex)
 1326                    {
 1327                        return denseIndex;
 328                    }
 0329                }
 2330            }
 331
 3332            return -1;
 4333        }
 334
 335        /// <summary>
 336        ///     Gets the value of the sparse array at the given index,
 337        ///     or -1 if the version number does not match.
 338        /// </summary>
 339        /// <param name="sparseIndex">The index in the sparse array to check against.</param>
 340        /// <param name="version">The version number associated with the sparse index.</param>
 341        /// <param name="versionArray">The array containing the version number to check against.</param>
 342        /// <returns>The dense index pointed to by the current sparse index, or -1 if invalid.</returns>
 343        public int GetDenseIndexWithVersionCheck(int sparseIndex, ulong version, ulong* versionArray)
 4344        {
 4345            int denseIndex = SparseArray[sparseIndex];
 4346            ulong versionAtSparseIndex = versionArray[sparseIndex];
 347
 4348            if (version == versionAtSparseIndex)
 2349            {
 2350                return denseIndex;
 351            }
 352
 2353            return -1;
 4354        }
 355
 356        /// <summary>
 357        ///     Gets the value of the sparse array at the given index,
 358        ///     or -1 if the given sparse index is invalid..
 359        /// </summary>
 360        /// <param name="sparseIndex">The index in the sparse array to check against.</param>
 361        /// <param name="version">The version number associated with the sparse index.</param>
 362        /// <param name="versionArray">The array containing the version number to check against.</param>
 363        /// <returns>The dense index pointed to by the current sparse index, or -1 if invalid.</returns>
 364        public int GetDenseIndexWithBoundsAndVersionCheck(int sparseIndex, ulong version, ulong* versionArray)
 7365        {
 7366            if (sparseIndex >= 0 && sparseIndex < Length)
 5367            {
 5368                int denseIndex = SparseArray[sparseIndex];
 5369                ulong versionAtSparseIndex = versionArray[sparseIndex];
 370
 5371                if (versionAtSparseIndex == version && denseIndex < Count && denseIndex >= 0)
 2372                {
 2373                    int sparseIndexAtDenseIndex = DenseArray[denseIndex];
 374
 2375                    if (sparseIndex == sparseIndexAtDenseIndex)
 2376                    {
 2377                        return denseIndex;
 378                    }
 0379                }
 3380            }
 381
 5382            return -1;
 7383        }
 384
 385        /// <summary>
 386        ///     Removes the entry corresponding to the sparse index if the entry is within bounds and currently in use.
 387        /// </summary>
 388        /// <param name="sparseIndexToRemove">The sparse index corresponding to the entry to remove. Cleared to -1 in th
 389        /// <param name="dataIndexToSwapFrom">
 390        ///     Set the data array value at this index to default after swapping with the data array
 391        ///     value at indexToSwapTo.
 392        /// </param>
 393        /// <param name="dataIndexToSwapTo">Replace the data array value at this index with the data array value at inde
 394        /// <returns>True if the index reference was valid, and thus removed.</returns>
 395        public bool RemoveWithBoundsCheck(ref int sparseIndexToRemove, out int dataIndexToSwapFrom, out int dataIndexToS
 4396        {
 4397            dataIndexToSwapFrom = -1;
 4398            dataIndexToSwapTo = -1;
 4399            bool didRemove = false;
 4400            if (sparseIndexToRemove >= 0 && sparseIndexToRemove < Length)
 2401            {
 2402                int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 403
 2404                if (denseIndexToRemove >= 0 && denseIndexToRemove < Count)
 1405                {
 1406                    int sparseIndexAtDenseIndex = DenseArray[denseIndexToRemove];
 1407                    int newLength = Count - 1;
 1408                    int sparseIndexBeingSwapped = DenseArray[newLength];
 409
 1410                    if (denseIndexToRemove < Count && sparseIndexAtDenseIndex == sparseIndexToRemove)
 1411                    {
 1412                        didRemove = true;
 413                        // Swap the entry being removed with the last entry.
 1414                        SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1415                        DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 416
 1417                        dataIndexToSwapFrom = newLength;
 1418                        dataIndexToSwapTo = denseIndexToRemove;
 419
 420                        // Clear the dense index, for debugging purposes
 1421                        DenseArray[newLength] = -1;
 422
 423                        // Add the sparse index to the free list.
 1424                        SparseArray[sparseIndexToRemove] = FreeIndex;
 1425                        FreeIndex = sparseIndexToRemove;
 426
 1427                        Count = newLength;
 1428                    }
 1429                }
 2430            }
 431
 4432            sparseIndexToRemove = -1;
 433
 4434            return didRemove;
 4435        }
 436
 437        /// <summary>
 438        ///     Removes the associated sparse/dense index pair from active use.
 439        ///     calls.
 440        /// </summary>
 441        /// <param name="sparseIndexToRemove">The sparse index to remove.</param>
 442        /// <param name="version">
 443        ///     The version number of the int used to access the sparse index. Used to guard against accessing
 444        ///     indices that have been removed and reused.
 445        /// </param>
 446        /// <param name="versionArray">The array containing the version number to check against.</param>
 447        /// <param name="indexToSwapFrom">
 448        ///     Set the data array value at this index to default after swapping with the data array
 449        ///     value at indexToSwapTo.
 450        /// </param>
 451        /// <param name="indexToSwapTo">Replace the data array value at this index with the data array value at indexToS
 452        /// <returns>True if the element was successfully removed.</returns>
 453        public bool RemoveWithBoundsAndVersionChecks(ref int sparseIndexToRemove, ulong version, ulong* versionArray, ou
 6454        {
 6455            indexToSwapFrom = -1;
 6456            indexToSwapTo = -1;
 6457            bool didRemove = false;
 6458            if (sparseIndexToRemove >= 0 && sparseIndexToRemove < Length)
 3459            {
 3460                ulong sparseIndexVersion = versionArray[sparseIndexToRemove];
 3461                int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 462
 3463                if (sparseIndexVersion == version && denseIndexToRemove >= 0 && denseIndexToRemove < Count)
 2464                {
 2465                    int sparseIndexAtDenseIndex = DenseArray[denseIndexToRemove];
 2466                    int newLength = Count - 1;
 2467                    int sparseIndexBeingSwapped = DenseArray[newLength];
 468
 2469                    if (denseIndexToRemove < Count && sparseIndexAtDenseIndex == sparseIndexToRemove)
 2470                    {
 2471                        didRemove = true;
 2472                        versionArray[sparseIndexToRemove] = sparseIndexVersion + 1;
 473                        // Swap the entry being removed with the last entry.
 2474                        SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 2475                        DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 476
 2477                        indexToSwapFrom = newLength;
 2478                        indexToSwapTo = denseIndexToRemove;
 479
 480                        // Clear the dense index, for debugging purposes
 2481                        DenseArray[newLength] = -1;
 482
 483                        // Add the sparse index to the free list.
 2484                        SparseArray[sparseIndexToRemove] = FreeIndex;
 2485                        FreeIndex = sparseIndexToRemove;
 486
 2487                        Count = newLength;
 2488                    }
 2489                }
 3490            }
 491
 6492            sparseIndexToRemove = -1;
 493
 6494            return didRemove;
 6495        }
 496
 497        /// <summary>
 498        ///     Removes the associated sparse/dense index pair from active use.
 499        /// </summary>
 500        /// <param name="sparseIndexToRemove">The sparse index to remove.</param>
 501        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 502        public void RemoveUnchecked(int sparseIndexToRemove)
 1503        {
 1504            int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 1505            int newLength = Count - 1;
 1506            int sparseIndexBeingSwapped = DenseArray[newLength];
 507
 508            // Swap the entry being removed with the last entry.
 1509            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1510            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 511
 512            // Clear the dense  index, for debugging purposes
 1513            DenseArray[newLength] = -1;
 514
 515            // Add the sparse index to the free list.
 1516            SparseArray[sparseIndexToRemove] = FreeIndex;
 1517            FreeIndex = sparseIndexToRemove;
 518
 1519            Count = newLength;
 1520        }
 521
 522        /// <summary>
 523        ///     Removes the associated sparse/dense index pair from active use and increments the version.
 524        /// </summary>
 525        /// <param name="sparseIndexToRemove">The sparse index to remove.</param>
 526        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 527        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 528        public void RemoveUnchecked(int sparseIndexToRemove, ulong* versionArray)
 1529        {
 1530            int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 1531            int newLength = Count - 1;
 1532            int sparseIndexBeingSwapped = DenseArray[newLength];
 533
 534            // Swap the entry being removed with the last entry.
 1535            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1536            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 537
 538            // Clear the dense  index, for debugging purposes
 1539            DenseArray[newLength] = -1;
 540
 541            // Add the sparse index to the free list.
 1542            SparseArray[sparseIndexToRemove] = FreeIndex;
 1543            versionArray[sparseIndexToRemove] += 1;
 1544            FreeIndex = sparseIndexToRemove;
 545
 1546            Count = newLength;
 1547        }
 548
 549        /// <summary>
 550        ///     Removes the associated sparse/dense index pair from active use.
 551        ///     Out parameters used to manage parallel data arrays.
 552        /// </summary>
 553        /// <param name="sparseIndexToRemove">The sparse index to remove.</param>
 554        /// <param name="indexToSwapTo">Replace the data array value at this index with the data array value at indexToS
 555        /// <param name="indexToSwapFrom">
 556        ///     Set the data array value at this index to default after swapping with the data array
 557        ///     value at indexToSwapTo.
 558        /// </param>
 559        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 560        public void RemoveUnchecked(int sparseIndexToRemove, out int indexToSwapFrom, out int indexToSwapTo)
 1561        {
 1562            int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 1563            int newLength = Count - 1;
 1564            int sparseIndexBeingSwapped = DenseArray[newLength];
 565
 566            // Swap the entry being removed with the last entry.
 1567            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1568            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 569
 570            // Clear the dense  index, for debugging purposes
 1571            DenseArray[newLength] = -1;
 572
 573            // Add the sparse index to the free list.
 1574            SparseArray[sparseIndexToRemove] = FreeIndex;
 1575            FreeIndex = sparseIndexToRemove;
 576
 1577            Count = newLength;
 578
 1579            indexToSwapTo = denseIndexToRemove;
 1580            indexToSwapFrom = newLength;
 1581        }
 582
 583        /// <summary>
 584        ///     Removes the associated sparse/dense index pair from active use and increments the version.
 585        ///     Out parameters used to manage parallel data arrays.
 586        /// </summary>
 587        /// <param name="sparseIndexToRemove">The sparse index to remove.</param>
 588        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 589        /// <param name="indexToSwapTo">Replace the data array value at this index with the data array value at indexToS
 590        /// <param name="indexToSwapFrom">
 591        ///     Set the data array value at this index to default after swapping with the data array
 592        ///     value at indexToSwapTo.
 593        /// </param>
 594        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 595        public void RemoveUnchecked(int sparseIndexToRemove, ulong* versionArray, out int indexToSwapFrom, out int index
 2596        {
 2597            int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 2598            int newLength = Count - 1;
 2599            int sparseIndexBeingSwapped = DenseArray[newLength];
 600
 601            // Swap the entry being removed with the last entry.
 2602            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 2603            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 604
 605            // Clear the dense  index, for debugging purposes
 2606            DenseArray[newLength] = -1;
 607
 608            // Add the sparse index to the free list.
 2609            SparseArray[sparseIndexToRemove] = FreeIndex;
 2610            versionArray[sparseIndexToRemove] += 1;
 2611            FreeIndex = sparseIndexToRemove;
 612
 2613            Count = newLength;
 614
 2615            indexToSwapTo = denseIndexToRemove;
 2616            indexToSwapFrom = newLength;
 2617        }
 618
 619        /// <summary>
 620        ///     Removes the associated sparse/dense index pair from active use.
 621        /// </summary>
 622        /// <param name="denseIndexToRemove">The dense index associated with the sparse index to remove.</param>
 623        public void RemoveUncheckedFromDenseIndex(int denseIndexToRemove)
 1624        {
 1625            int sparseIndexToRemove = DenseArray[denseIndexToRemove];
 1626            int newLength = Count - 1;
 1627            int sparseIndexBeingSwapped = DenseArray[newLength];
 628
 629            // Swap the entry being removed with the last entry.
 1630            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1631            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 632
 633            // Clear the dense  index, for debugging purposes
 1634            DenseArray[newLength] = -1;
 635
 636            // Add the sparse index to the free list.
 1637            SparseArray[sparseIndexToRemove] = FreeIndex;
 1638            FreeIndex = sparseIndexToRemove;
 639
 1640            Count = newLength;
 1641        }
 642
 643        /// <summary>
 644        ///     Removes the associated sparse/dense index pair from active use.
 645        /// </summary>
 646        /// <param name="denseIndexToRemove">The dense index associated with the sparse index to remove.</param>
 647        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 648        public void RemoveUncheckedFromDenseIndex(int denseIndexToRemove, ulong* versionArray)
 1649        {
 1650            int sparseIndexToRemove = DenseArray[denseIndexToRemove];
 1651            int newLength = Count - 1;
 1652            int sparseIndexBeingSwapped = DenseArray[newLength];
 653
 654            // Swap the entry being removed with the last entry.
 1655            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1656            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 657
 658            // Clear the dense  index, for debugging purposes
 1659            DenseArray[newLength] = -1;
 660
 661            // Add the sparse index to the free list.
 1662            SparseArray[sparseIndexToRemove] = FreeIndex;
 1663            versionArray[sparseIndexToRemove] += 1;
 1664            FreeIndex = sparseIndexToRemove;
 665
 1666            Count = newLength;
 1667        }
 668
 669        /// <summary>
 670        ///     Removes the associated sparse/dense index pair from active use.
 671        ///     Out parameter used to manage parallel data arrays.
 672        /// </summary>
 673        /// <param name="denseIndexToRemove">The sparse index to remove.</param>
 674        /// <param name="indexToSwapFrom">
 675        ///     Set the data array value at this index to default after swapping with the data array
 676        ///     value at denseIndexToRemove.
 677        /// </param>
 678        public void RemoveUncheckedFromDenseIndex(int denseIndexToRemove, out int indexToSwapFrom)
 1679        {
 1680            int sparseIndexToRemove = DenseArray[denseIndexToRemove];
 1681            int newLength = Count - 1;
 1682            int sparseIndexBeingSwapped = DenseArray[newLength];
 683
 684            // Swap the entry being removed with the last entry.
 1685            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1686            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 687
 688            // Clear the dense  index, for debugging purposes
 1689            DenseArray[newLength] = -1;
 690
 691            // Add the sparse index to the free list.
 1692            SparseArray[sparseIndexToRemove] = FreeIndex;
 1693            FreeIndex = sparseIndexToRemove;
 694
 1695            Count = newLength;
 696
 1697            indexToSwapFrom = newLength;
 1698        }
 699
 700        /// <summary>
 701        ///     Removes the associated sparse/dense index pair from active use.
 702        ///     Out parameter used to manage parallel data arrays.
 703        /// </summary>
 704        /// <param name="denseIndexToRemove">The sparse index to remove.</param>
 705        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 706        /// <param name="indexToSwapFrom">
 707        ///     Set the data array value at this index to default after swapping with the data array
 708        ///     value at denseIndexToRemove.
 709        /// </param>
 710        public void RemoveUncheckedFromDenseIndex(int denseIndexToRemove, ulong* versionArray, out int indexToSwapFrom)
 1711        {
 1712            int sparseIndexToRemove = DenseArray[denseIndexToRemove];
 1713            int newLength = Count - 1;
 1714            int sparseIndexBeingSwapped = DenseArray[newLength];
 715
 716            // Swap the entry being removed with the last entry.
 1717            SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1718            DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 719
 720            // Clear the dense  index, for debugging purposes
 1721            DenseArray[newLength] = -1;
 722
 723            // Add the sparse index to the free list.
 1724            SparseArray[sparseIndexToRemove] = FreeIndex;
 1725            versionArray[sparseIndexToRemove] += 1;
 1726            FreeIndex = sparseIndexToRemove;
 727
 1728            Count = newLength;
 729
 1730            indexToSwapFrom = newLength;
 1731        }
 732
 733        /// <summary>
 734        ///     Attempts to remove the associated sparse/dense index pair from active use and increments the version if 
 735        ///     Out parameters used to manage parallel data arrays.
 736        /// </summary>
 737        /// <param name="sparseIndexToRemove">The sparse index to remove.</param>
 738        /// <param name="version">
 739        ///     The version number of the int used to access the sparse index. Used to guard against accessing
 740        ///     indices that have been removed and reused.
 741        /// </param>
 742        /// <param name="versionArray">The array containing the version number to check against.</param>
 743        /// <param name="indexToSwapTo">Replace the data array value at this index with the data array value at indexToS
 744        /// <param name="indexToSwapFrom">
 745        ///     Set the data array value at this index to default after swapping with the data array
 746        ///     value at indexToSwapTo.
 747        /// </param>
 748        /// <returns>True if the entry was valid and thus removed.</returns>
 749        public bool RemoveWithVersionCheck(int sparseIndexToRemove, ulong version, ulong* versionArray, out int indexToS
 2750        {
 2751            int denseIndexToRemove = SparseArray[sparseIndexToRemove];
 2752            ulong versionAtSparseIndex = versionArray[sparseIndexToRemove];
 753
 2754            indexToSwapFrom = -1;
 2755            indexToSwapTo = -1;
 756
 2757            bool succeeded = versionAtSparseIndex == version;
 758
 2759            if (succeeded)
 1760            {
 1761                int newLength = Count - 1;
 1762                int sparseIndexBeingSwapped = DenseArray[newLength];
 763
 764                // Swap the entry being removed with the last entry.
 1765                SparseArray[sparseIndexBeingSwapped] = denseIndexToRemove;
 1766                DenseArray[denseIndexToRemove] = sparseIndexBeingSwapped;
 767
 768                // Clear the dense  index, for debugging purposes
 1769                DenseArray[newLength] = -1;
 770
 771                // Add the sparse index to the free list.
 1772                SparseArray[sparseIndexToRemove] = FreeIndex;
 1773                versionArray[sparseIndexToRemove] += 1;
 1774                FreeIndex = sparseIndexToRemove;
 775
 1776                Count = newLength;
 777
 1778                indexToSwapTo = denseIndexToRemove;
 1779                indexToSwapFrom = newLength;
 1780            }
 781
 2782            return succeeded;
 2783        }
 784
 785        /// <summary>
 786        ///     Clear the dense and sparse arrays.
 787        /// </summary>
 788        public void Clear()
 1789        {
 1790            int capacity = Length;
 18791            for (int i = 0; i < capacity; i++)
 8792            {
 8793                DenseArray[i] = -1;
 8794                SparseArray[i] = i + 1;
 8795            }
 796
 1797            FreeIndex = 0;
 1798            Count = 0;
 1799        }
 800
 801        /// <summary>
 802        ///     Clear the dense and sparse arrays.
 803        /// </summary>
 804        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 805        public void Clear(ulong* versionArray)
 1806        {
 1807            int capacity = Length;
 18808            for (int i = 0; i < capacity; i++)
 8809            {
 8810                DenseArray[i] = -1;
 8811                SparseArray[i] = i + 1;
 8812                versionArray[i] += 1;
 8813            }
 814
 1815            FreeIndex = 0;
 1816            Count = 0;
 1817        }
 818
 819        /// <summary>
 820        ///     Clear the dense and sparse arrays and reset the version array.
 821        ///     Note: Only clear the version array if you are sure there are no outstanding dependencies on version numb
 822        /// </summary>
 823        /// ///
 824        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 825        public void ClearWithVersionArrayReset(ulong* versionArray)
 1826        {
 1827            int capacity = Length;
 18828            for (int i = 0; i < capacity; i++)
 8829            {
 8830                DenseArray[i] = -1;
 8831                SparseArray[i] = i + 1;
 8832                versionArray[i] = 1;
 8833            }
 834
 1835            FreeIndex = 0;
 1836            Count = 0;
 1837        }
 838
 839        /// <summary>
 840        ///     Reallocate the dense and sparse arrays with additional capacity.
 841        /// </summary>
 842        /// <param name="extraCapacity">How many indices to expand the dense and sparse arrays by.</param>
 843        public void Expand(int extraCapacity)
 1844        {
 1845            int currentCapacity = Length;
 1846            int newCapacity = currentCapacity + extraCapacity;
 847
 1848            newCapacity = newCapacity > MinimumCapacity ? newCapacity : MinimumCapacity;
 1849            --newCapacity;
 1850            newCapacity |= newCapacity >> 1;
 1851            newCapacity |= newCapacity >> 2;
 1852            newCapacity |= newCapacity >> 4;
 1853            newCapacity |= newCapacity >> 8;
 1854            newCapacity |= newCapacity >> 16;
 1855            ++newCapacity;
 856
 1857            void* newData = Allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, newCapacity * 2);
 858
 1859            UnsafeUtility.MemCpy(newData, Data, sizeof(int) * currentCapacity);
 1860            int* newSparseArray = (int*)newData;
 18861            for (int i = currentCapacity; i < newCapacity; i++)
 8862            {
 8863                newSparseArray[i] = i + 1;
 8864            }
 865
 1866            int* newDenseArray = newSparseArray + newCapacity;
 1867            UnsafeUtility.MemCpy(newDenseArray, DenseArray, sizeof(int) * currentCapacity);
 18868            for (int i = currentCapacity; i < newCapacity; i++)
 8869            {
 8870                newDenseArray[i] = -1;
 8871            }
 872
 1873            Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, currentCapacity * 2);
 874
 1875            Data = newData;
 1876            Length = newCapacity;
 1877        }
 878
 879        /// <summary>
 880        ///     Reallocate the dense and sparse arrays with additional capacity.
 881        /// </summary>
 882        /// <param name="extraCapacity">How many indices to expand the dense and sparse arrays by.</param>
 883        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 884        public void Expand(int extraCapacity, ref ulong* versionArray)
 1885        {
 1886            int currentCapacity = Length;
 1887            int newCapacity = currentCapacity + extraCapacity;
 888
 1889            newCapacity = newCapacity > MinimumCapacity ? newCapacity : MinimumCapacity;
 1890            --newCapacity;
 1891            newCapacity |= newCapacity >> 1;
 1892            newCapacity |= newCapacity >> 2;
 1893            newCapacity |= newCapacity >> 4;
 1894            newCapacity |= newCapacity >> 8;
 1895            newCapacity |= newCapacity >> 16;
 1896            ++newCapacity;
 897
 1898            void* newData = Allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, newCapacity * 2);
 899
 1900            UnsafeUtility.MemCpy(newData, Data, sizeof(int) * currentCapacity);
 1901            int* newSparseArray = (int*)newData;
 18902            for (int i = currentCapacity; i < newCapacity; i++)
 8903            {
 8904                newSparseArray[i] = i + 1;
 8905            }
 906
 1907            int* newDenseArray = newSparseArray + newCapacity;
 1908            UnsafeUtility.MemCpy(newDenseArray, DenseArray, sizeof(int) * currentCapacity);
 18909            for (int i = currentCapacity; i < newCapacity; i++)
 8910            {
 8911                newDenseArray[i] = -1;
 8912            }
 913
 1914            ulong* newVersionArray = (ulong*)Allocator.Allocate(sizeof(ulong), JobsUtility.CacheLineSize, currentCapacit
 1915            UnsafeUtility.MemCpy(newVersionArray, versionArray, sizeof(ulong) * currentCapacity);
 18916            for (int i = currentCapacity; i < newCapacity; i++)
 8917            {
 8918                newVersionArray[i] = 1;
 8919            }
 920
 1921            Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, currentCapacity * 2);
 1922            Allocator.Free(versionArray, sizeof(ulong), JobsUtility.CacheLineSize, currentCapacity);
 1923            versionArray = newVersionArray;
 924
 1925            Data = newData;
 1926            Length = newCapacity;
 1927        }
 928
 929        /// <summary>
 930        /// Reallocate the dense and sparse arrays with additional capacity if there are not at least <paramref name="nu
 931        /// </summary>
 932        /// <param name="numberToReserve">The number of unused entries to ensure capacity for.</param>
 933        public void Reserve(int numberToReserve)
 1934        {
 1935            int currentCapacity = Length;
 1936            int currentCount = Count;
 1937            int newCapacity = currentCount + numberToReserve;
 938
 1939            if (newCapacity > currentCapacity)
 1940            {
 1941                newCapacity = newCapacity > MinimumCapacity ? newCapacity : MinimumCapacity;
 1942                --newCapacity;
 1943                newCapacity |= newCapacity >> 1;
 1944                newCapacity |= newCapacity >> 2;
 1945                newCapacity |= newCapacity >> 4;
 1946                newCapacity |= newCapacity >> 8;
 1947                newCapacity |= newCapacity >> 16;
 1948                ++newCapacity;
 949
 1950                void* newData = Allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, newCapacity * 2);
 951
 1952                UnsafeUtility.MemCpy(newData, Data, sizeof(int) * currentCapacity);
 1953                int* newSparseArray = (int*)newData;
 18954                for (int i = currentCapacity; i < newCapacity; i++)
 8955                {
 8956                    newSparseArray[i] = i + 1;
 8957                }
 958
 1959                int* newDenseArray = newSparseArray + newCapacity;
 1960                UnsafeUtility.MemCpy(newDenseArray, DenseArray, sizeof(int) * currentCapacity);
 18961                for (int i = currentCapacity; i < newCapacity; i++)
 8962                {
 8963                    newDenseArray[i] = -1;
 8964                }
 965
 1966                Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, currentCapacity * 2);
 967
 1968                Data = newData;
 1969                Length = newCapacity;
 1970            }
 1971        }
 972
 973        /// <summary>
 974        /// Reallocate the dense and sparse arrays with additional capacity if there are not at least <paramref name="nu
 975        /// </summary>
 976        /// <param name="numberToReserve">The number of unused entries to ensure capacity for.</param>
 977        /// <param name="versionArray">Enables detection of use-after-free errors when using sparse indices as reference
 978        public void Reserve(int numberToReserve,  ref ulong* versionArray)
 1979        {
 1980            int currentCapacity = Length;
 1981            int currentCount = Count;
 1982            int newCapacity = currentCount + numberToReserve;
 983
 1984            if (newCapacity > currentCapacity)
 1985            {
 1986                newCapacity = newCapacity > MinimumCapacity ? newCapacity : MinimumCapacity;
 1987                --newCapacity;
 1988                newCapacity |= newCapacity >> 1;
 1989                newCapacity |= newCapacity >> 2;
 1990                newCapacity |= newCapacity >> 4;
 1991                newCapacity |= newCapacity >> 8;
 1992                newCapacity |= newCapacity >> 16;
 1993                ++newCapacity;
 994
 1995                void* newData = Allocator.Allocate(sizeof(int), JobsUtility.CacheLineSize, newCapacity * 2);
 996
 1997                UnsafeUtility.MemCpy(newData, Data, sizeof(int) * currentCapacity);
 1998                int* newSparseArray = (int*)newData;
 18999                for (int i = currentCapacity; i < newCapacity; i++)
 81000                {
 81001                    newSparseArray[i] = i + 1;
 81002                }
 1003
 11004                int* newDenseArray = newSparseArray + newCapacity;
 11005                UnsafeUtility.MemCpy(newDenseArray, DenseArray, sizeof(int) * currentCapacity);
 181006                for (int i = currentCapacity; i < newCapacity; i++)
 81007                {
 81008                    newDenseArray[i] = -1;
 81009                }
 1010
 11011                ulong* newVersionArray = (ulong*)Allocator.Allocate(sizeof(ulong), JobsUtility.CacheLineSize, currentCap
 11012                UnsafeUtility.MemCpy(newVersionArray, versionArray, sizeof(ulong) * currentCapacity);
 181013                for (int i = currentCapacity; i < newCapacity; i++)
 81014                {
 81015                    newVersionArray[i] = 1;
 81016                }
 1017
 11018                Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, currentCapacity * 2);
 11019                Allocator.Free(versionArray, sizeof(ulong), JobsUtility.CacheLineSize, currentCapacity);
 11020                versionArray = newVersionArray;
 1021
 11022                Data = newData;
 11023                Length = newCapacity;
 11024            }
 11025        }
 1026
 1027        public void Dispose()
 11028        {
 11029            if (Data != null)
 11030            {
 11031                Allocator.Free(Data, sizeof(int), JobsUtility.CacheLineSize, Length * 2);
 11032                Data = null;
 11033                Length = 0;
 11034                Count = 0;
 11035                FreeIndex = 0;
 11036                Allocator = default;
 11037            }
 11038        }
 1039
 1040        public void DisposeVersionArray(ref ulong* versionArray)
 11041        {
 11042            Allocator.Free(versionArray, sizeof(ulong), JobsUtility.CacheLineSize, Length);
 11043            versionArray = null;
 11044        }
 1045    }
 1046}

Methods/Properties

DenseArray()
SparseArray()
UnsafeSparseSet(System.Int32, Unity.Collections.AllocatorManager/AllocatorHandle)
UnsafeSparseSet(System.Int32, Unity.Collections.AllocatorManager/AllocatorHandle, System.UInt64*&)
AddWithExpandCheck(System.Int32, System.Int32&, System.Int32&)
AddWithExpandCheck(System.Int32, System.Int32&, System.Int32&, System.UInt64*&)
AddUnchecked(System.Int32&, System.Int32&)
AddUnchecked(System.Int32&, System.Int32&, System.UInt64*, System.UInt64&)
GetDenseIndexUnchecked(System.Int32)
GetDenseIndexWithBoundsCheck(System.Int32)
GetDenseIndexWithVersionCheck(System.Int32, System.UInt64, System.UInt64*)
GetDenseIndexWithBoundsAndVersionCheck(System.Int32, System.UInt64, System.UInt64*)
RemoveWithBoundsCheck(System.Int32&, System.Int32&, System.Int32&)
RemoveWithBoundsAndVersionChecks(System.Int32&, System.UInt64, System.UInt64*, System.Int32&, System.Int32&)
RemoveUnchecked(System.Int32)
RemoveUnchecked(System.Int32, System.UInt64*)
RemoveUnchecked(System.Int32, System.Int32&, System.Int32&)
RemoveUnchecked(System.Int32, System.UInt64*, System.Int32&, System.Int32&)
RemoveUncheckedFromDenseIndex(System.Int32)
RemoveUncheckedFromDenseIndex(System.Int32, System.UInt64*)
RemoveUncheckedFromDenseIndex(System.Int32, System.Int32&)
RemoveUncheckedFromDenseIndex(System.Int32, System.UInt64*, System.Int32&)
RemoveWithVersionCheck(System.Int32, System.UInt64, System.UInt64*, System.Int32&, System.Int32&)
Clear()
Clear(System.UInt64*)
ClearWithVersionArrayReset(System.UInt64*)
Expand(System.Int32)
Expand(System.Int32, System.UInt64*&)
Reserve(System.Int32)
Reserve(System.Int32, System.UInt64*&)
Dispose()
DisposeVersionArray(System.UInt64*&)