Rasagar/Library/PackageCache/com.unity.collections/Documentation~/allocator-custom-define.md

96 lines
6.8 KiB
Markdown
Raw Normal View History

2024-08-26 13:07:20 -07:00
# Custom allocator overview
You can use a custom allocator for specific memory allocation needs. To create a custom allocator, it must contain an allocator handle of type [`AllocatorManager.AllocatorHandle`](xref:Unity.Collections.AllocatorManager.AllocatorHandle) and implement the interface, [`AllocatorManager.IAllocator`](xref:Unity.Collections.AllocatorManager.IAllocator). After you create a custom allocator, you need to register it in a global allocator table in [`AllocatorManager`](xref:Unity.Collections.AllocatorManager).
## Add the AllocatorManager.AllocatorHandle type to the custom allocator
A custom allocator must contain an allocator handle of type [`AllocatorManager.AllocatorHandle`](xref:Unity.Collections.AllocatorManager.AllocatorHandle). An allocator handle includes the following:
* `Version`: A 2 byte unsigned version number. Only the lower 15 bits are valid.
* `Index`: A 2 byte unsigned index of the global allocator table obtained during registration.
* Method to add a safety handle to the list of child safety handles of the allocator handle.
* Method to add a child allocator to the list of child allocators of the allocator handle.
* A rewind method to invalidate and unregister all the child allocators, invalidate all the child safety handles of the allocator handle, and increment the allocator handle' `Version` and `OfficialVersion`.
## Implement AllocatorManager.IAllocator interface
To define a custom allocator, you must implement the interface [`AllocatorManager.IAllocator`](xref:Unity.Collections.AllocatorManager.IAllocator) which includes:
* [`Function`](xref:Unity.Collections.AllocatorManager.IAllocator.Function): A property that gets the allocator function of delegate [`TryFunction`](xref:Unity.Collections.AllocatorManager.TryFunction). The allocator function can allocate, deallocate, and reallocate memory.
* [`Try`](xref:Unity.Collections.AllocatorManager.IAllocator.Try(Unity.Collections.AllocatorManager.Block@)): A method that the allocator function invokes to allocate, deallocate, or reallocate memory.
* [`Handle`](xref:Unity.Collections.AllocatorManager.IAllocator.Handle): A property that gets and sets the allocator handle which is of type [`AllocatorManager.AllocatorHandle`](xref:Unity.Collections.AllocatorManager.AllocatorHandle).
* [`ToAllocator`](xref:Unity.Collections.AllocatorManager.IAllocator.ToAllocator): A property that casts the allocator handle index to the enum `Allocator`.
* [`IsCustomAllocator`](xref:Unity.Collections.AllocatorManager.IAllocator.IsCustomAllocator): A property that checks whether the allocator is a custom allocator. An allocator is a custom allocator if its handle `Index` is larger or equal to [`AllocatorManager.FirstUserIndex`](xref:Unity.Collections.AllocatorManager.FirstUserIndex).
* [`IsAutoDispose`](xref:Unity.Collections.AllocatorManager.AllocatorHandle.IsAutoDispose): A property that checks whether the allocator is able to dispose individual allocations. True if disposing an individual allocation is a no-op.
Because `AllocatorManager.IAllocator` implements `IDisposable`, your custom allocator must implement the `Dispose` method.
The following is an example of how to set up the `IAllocator` interface and its required properties except the `Try` and `AllocatorFunction` method:
```c#
// A custom allocator must implement AllocatorManager.IAllocator interface
[BurstCompile(CompileSynchronously = true)]
internal struct ExampleCustomAllocator : AllocatorManager.IAllocator
{
// A custom allocator must contain AllocatorManager.AllocatorHandle
AllocatorManager.AllocatorHandle m_handle;
// Implement the Function property required by IAllocator interface
public AllocatorManager.TryFunction Function => AllocatorFunction;
// Implement the Handle property required by IAllocator interface
public AllocatorManager.AllocatorHandle Handle { get { return m_handle; } set { m_handle = value; } }
// Implement the ToAllocator property required by IAllocator interface
public Allocator ToAllocator { get { return m_handle.ToAllocator; } }
// Implement the IsCustomAllocator property required by IAllocator interface
public bool IsCustomAllocator { get { return m_handle.IsCustomAllocator; } }
// Implement the IsAutoDispose property required by IAllocator interface
// Allocations made by this example allocator are not automatically disposed.
// This implementation can be skipped because the default implementation of
// this property is false.
public bool IsAutoDispose { get { return false; } }
// Implement the Dispose method required by IDisposable interface because
// AllocatorManager.IAllocator implements IDisposable
public void Dispose()
{
// Make sure no memory leaks
Assert.AreEqual(0, m_allocationCount);
m_handle.Dispose();
}
}
```
The `Try` method tells a custom allocator how to allocate or deallocate memory. The following is an example of the`Try` method where a custom allocator allocates memory from `Allocator.Persistant`, initializes the allocated memory with a user configured value, and increments an allocation count. The custom allocator also decrements the allocation count when deallocating the allocated memory.
[!code-cs[Try method of allocate/deallocate memory](../Unity.Collections.Tests/AllocatorCustomTests.cs#allocator-custom-try)]
Example method `AllocatorFunction` below shows an allocator function of the custom allocator.
[!code-cs[Allocator function](../Unity.Collections.Tests/AllocatorCustomTests.cs#allocator-custom-allocator-function)]
## Global allocator table
The global allocator table in [`AllocatorManager`](xref:Unity.Collections.AllocatorManager) stores all the necessary information for custom allocators to work. When you instantiate a custom allocator, you must register the allocator in the global allocator table. The table stores the following information:
* A pointer to the custom allocator instance
* A pointer to the allocator function of the custom allocator instance
* The current official version of the custom allocator instance, lower 15 bits of a 2 byte unsigned integer value
* A list of child safety handles of native containers that are created using the custom allocator instance
* A list of child allocators that are allocated using the custom allocator instance
* A bit flag indicating whether the custom allocator is able to dispose individual allocations
## Custom allocator example
The following is an example of a custom allocator that has an `AllocatorManager.AllocatorHandle` and initializes the allocated memory with a user configured value and increments the allocation count. It also uses `AllocatorManager.TryFunction` to register the allocator on the global allocator table:
[!code-cs[Custom allocator example](../Unity.Collections.Tests/AllocatorCustomTests.cs#allocator-custom-example)]
## Further information
* [Use a custom allocator](allocator-custom-use.md)