124 lines
4.5 KiB
C#
124 lines
4.5 KiB
C#
|
#region allocator-rewindable-example
|
||
|
using System;
|
||
|
using NUnit.Framework;
|
||
|
using Unity.Collections;
|
||
|
|
||
|
// This is the example code used in
|
||
|
// Packages/com.unity.collections/Documentation~/allocator/allocator-rewindable.md
|
||
|
// Example user structure
|
||
|
internal struct ExampleStruct
|
||
|
{
|
||
|
// Use AllocatorHelper to help creating a rewindable alloctor
|
||
|
AllocatorHelper<RewindableAllocator> rwdAllocatorHelper;
|
||
|
|
||
|
// Rewindable allocator property for accessibility
|
||
|
public ref RewindableAllocator RwdAllocator => ref rwdAllocatorHelper.Allocator;
|
||
|
|
||
|
// Create the rewindable allocator
|
||
|
void CreateRewindableAllocator(AllocatorManager.AllocatorHandle backgroundAllocator, int initialBlockSize, bool enableBlockFree = false)
|
||
|
{
|
||
|
// Allocate the rewindable allocator from backgroundAllocator and register the allocator
|
||
|
rwdAllocatorHelper = new AllocatorHelper<RewindableAllocator>(backgroundAllocator);
|
||
|
|
||
|
// Allocate the first memory block with initialBlockSize in bytes, and indicate whether
|
||
|
// to enable the rewindable allocator with individual block free through enableBlockFree
|
||
|
RwdAllocator.Initialize(initialBlockSize, enableBlockFree);
|
||
|
}
|
||
|
|
||
|
// Constructor of user structure
|
||
|
public ExampleStruct(int initialBlockSize)
|
||
|
{
|
||
|
this = default;
|
||
|
CreateRewindableAllocator(Allocator.Persistent, initialBlockSize, false);
|
||
|
}
|
||
|
|
||
|
// Dispose the user structure
|
||
|
public void Dispose()
|
||
|
{
|
||
|
DisposeRewindableAllocator();
|
||
|
}
|
||
|
|
||
|
#region allocator-rewindable-use
|
||
|
// Sample code to use rewindable allocator to allocate containers
|
||
|
public unsafe void UseRewindableAllocator(out NativeArray<int> nativeArray, out NativeList<int> nativeList, out byte* bytePtr)
|
||
|
{
|
||
|
// Use rewindable allocator to allocate a native array, no need to dispose the array manually
|
||
|
// CollectionHelper is required to create/allocate native array from a custom allocator.
|
||
|
nativeArray = CollectionHelper.CreateNativeArray<int, RewindableAllocator>(100, ref RwdAllocator);
|
||
|
nativeArray[0] = 0xFE;
|
||
|
|
||
|
// Use rewindable allocator to allocate a native list, do not need to dispose the list manually
|
||
|
nativeList = new NativeList<int>(RwdAllocator.Handle);
|
||
|
for (int i = 0; i < 50; i++)
|
||
|
{
|
||
|
nativeList.Add(i);
|
||
|
}
|
||
|
|
||
|
// Use custom allocator to allocate a byte buffer.
|
||
|
bytePtr = (byte*)AllocatorManager.Allocate(ref RwdAllocator, sizeof(byte), sizeof(byte), 10);
|
||
|
bytePtr[0] = 0xAB;
|
||
|
}
|
||
|
#endregion // allocator-rewindable-use
|
||
|
|
||
|
#region allocator-rewindable-free
|
||
|
// Free all allocations from the rewindable allocator
|
||
|
public void FreeRewindableAllocator()
|
||
|
{
|
||
|
RwdAllocator.Rewind();
|
||
|
}
|
||
|
#endregion // allocator-rewindable-free
|
||
|
|
||
|
#region allocator-rewindable-dispose
|
||
|
// Dispose the rewindable allocator
|
||
|
void DisposeRewindableAllocator()
|
||
|
{
|
||
|
// Dispose all the memory blocks in the rewindable allocator
|
||
|
RwdAllocator.Dispose();
|
||
|
// Unregister the rewindable allocator and dispose it
|
||
|
rwdAllocatorHelper.Dispose();
|
||
|
}
|
||
|
#endregion // allocator-rewindable-dispose
|
||
|
}
|
||
|
internal class ExampleStructSampleUsage
|
||
|
{
|
||
|
// Initial block size of the rewindable allocator.
|
||
|
const int IntialBlockSize = 128 * 1024;
|
||
|
|
||
|
[Test]
|
||
|
public unsafe void UseRewindableAllocator_Works()
|
||
|
{
|
||
|
ExampleStruct exampleStruct = new ExampleStruct(IntialBlockSize);
|
||
|
|
||
|
// Allocate native array and native list from rewindable allocator
|
||
|
exampleStruct.UseRewindableAllocator(out NativeArray<int> nativeArray, out NativeList<int> nativeList, out byte* bytePtr);
|
||
|
|
||
|
// Still able to access the native array, native list and byte buffer
|
||
|
Assert.AreEqual(nativeArray[0], 0xFE);
|
||
|
Assert.AreEqual(nativeList[10], 10);
|
||
|
Assert.AreEqual(bytePtr[0], 0xAB);
|
||
|
|
||
|
|
||
|
// Free all memories allocated from the rewindable allocator
|
||
|
// No need to dispose the native array and native list
|
||
|
exampleStruct.FreeRewindableAllocator();
|
||
|
|
||
|
#if ENABLE_UNITY_COLLECTIONS_CHECKS
|
||
|
// Object disposed exception throws because nativeArray is already disposed
|
||
|
Assert.Throws<ObjectDisposedException>(() =>
|
||
|
{
|
||
|
nativeArray[0] = 0xEF;
|
||
|
});
|
||
|
|
||
|
// Object disposed exception throws because nativeList is already disposed
|
||
|
Assert.Throws<ObjectDisposedException>(() =>
|
||
|
{
|
||
|
nativeList[10] = 0x10;
|
||
|
});
|
||
|
#endif
|
||
|
|
||
|
// Dispose the user structure
|
||
|
exampleStruct.Dispose();
|
||
|
}
|
||
|
}
|
||
|
#endregion // allocator-rewindable-example
|