Aliasing allocators
An alias is a collection which doesn't have its own allocation but instead shares the allocation of another collection, in whole or in part. For example, you can create an UnsafeList
that doesn't allocate its own memory but instead uses a NativeList
's allocation. Writing to this shared memory via the UnsafeList
affects the content of the NativeList
, and vice versa.
You don't need to dispose aliases, and calling Dispose
on an alias does nothing. Once an original is disposed, you can no longer use the aliases of the original:
NativeList<int> nums = new NativeList<int>(10, Allocator.TempJob);
nums.Length = 5;
// Create an array of 5 ints that aliases the content of the list.
NativeArray<int> aliasedNums = nums.AsArray();
// Modify the first element of both the array and the list.
aliasedNums[0] = 99;
// Only the original need be disposed.
nums.Dispose();
// Throws an ObjectDisposedException because disposing
// the original deallocates the aliased memory.
aliasedNums[0] = 99;
Aliasing is useful for the following situations:
- Getting a collection's data in the form of another collection type without copying the data. For example, you can create an
UnsafeList
that aliases aNativeArray
. - Getting a subrange of a collection's data without copying the data. For example, you can create an UnsafeList that aliases a subrange of another list or array.
- Array reinterpretation.
An Unsafe-
collection can alias a Native-
collection even though such cases undermine the safety checks. For example, if an UnsafeList
aliases a NativeList
, it's not safe to schedule a job that accesses one while also another job is scheduled that accesses the other, but the safety checks don't catch these cases.
Array reinterpretation
A reinterpretation of an array is an alias of the array that reads and writes the content as a different element type. For example, a NativeArray<int>
which reinterprets a NativeArray<ushort>
shares the same bytes, but it reads and writes the bytes as an int instead of a ushort. This is because each int is 4 bytes while each ushort is 2 bytes. Each int corresponds to two ushorts, and the reinterpretation has half the length of the original.
NativeArray<int> ints = new NativeArray<int>(10, Allocator.Temp);
// Length of the reinterpreted array is 20
// (because it has two shorts per one int of the original).
NativeArray<short> shorts = ints.Reinterpret<int, short>();
// Modifies the first 4 bytes of the array.
shorts[0] = 1;
shorts[1] = 1;
int val = ints[0]; // val is 65537 (2^16 + 2^0)
// Like with other aliased collections, only the original
// needs to be disposed.
ints.Dispose();
// Throws an ObjectDisposedException because disposing
// the original deallocates the aliased memory.
shorts[0] = 1;