I’m trying to create a read only NativeArray from a custom container so that any users of the array are required to mark the container as ReadOnly in jobs (and I suppose hopefully prevent any writes in general). It looks like the AtomicSafetyHandle is what I’ll be needing to manipulate to accomplish this but I really don’t understand how to make it work.
Below is a VERY simple example of what I’m trying to do
using System;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using Unity.Jobs;
using UnityEngine;
public class TestGetReadOnly : MonoBehaviour
{
[NativeContainer]
public unsafe struct SimpleContainer : IDisposable
{
private int* _ptr;
private int _count;
private AtomicSafetyHandle m_Safety;
public SimpleContainer(int count)
{
_ptr = (int*)UnsafeUtility.Malloc(
UnsafeUtility.SizeOf<int>() * count,
UnsafeUtility.AlignOf<int>(),
Allocator.Persistent);
_count = count;
m_Safety = AtomicSafetyHandle.Create();
}
public NativeArray<int> GetReadOnlyArray()
{
NativeArray<int> arr = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray<int>(
_ptr,
_count,
Allocator.Invalid);
NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref arr, m_Safety);
// TODO: I don't know what to do with my safety handle! I don't understand the secondary version if that's
// what I would use
return arr;
}
public void Dispose()
{
UnsafeUtility.Free(_ptr, Allocator.Persistent);
AtomicSafetyHandle.Release(m_Safety);
}
}
private struct BadJob : IJob
{
// Since I don't mark this as ReadOnly I want an exception!
public NativeArray<int> arr;
public void Execute()
{
}
}
private void Start()
{
SimpleContainer container = new SimpleContainer(10);
try
{
BadJob job = default;
job.arr = container.GetReadOnlyArray();
// I want this job to throw an exception!
job.Schedule().Complete();
Debug.Log("BAD! We didn't get an exception :'(");
}
catch
{
Debug.Log("Good we got an exception!");
throw;
}
finally
{
container.Dispose();
}
}
}
I want an exception when the job is scheduled since the container isn’t marked as read only. I’m happy to try to figure this out but I’m having a real hard time wrapping my head around how AtomicSafetyHandles work (for example, I don’t get the concept of secondary version at all).
Any help would be greatly appreciated!