Created
February 20, 2018 07:45
-
-
Save OswaldHurlem/959a12005f049375f1eab98c06572ae8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This doesn't seem to work properly | |
//#define USE_UNITY_PIN_FUNCTION | |
using System; | |
using System.Runtime.InteropServices; | |
using System.Threading; | |
using Unity.Collections; | |
using Unity.Collections.LowLevel.Unsafe; | |
using Unity.Jobs; | |
using UnityEngine; | |
using UnityEngine.Assertions; | |
// Trick for creating a temporary NativeSlice which points to the contents of a managed array. | |
// Good for mischief and bleeding-edge perf. BEWARE! Very likely to cause bugs now and break later. | |
public class Test : MonoBehaviour | |
{ | |
JobHandle jobHandle; | |
SliceAdapter<int> adapter; | |
int[] managedArray; | |
void Start() | |
{ | |
managedArray = new int[20]; | |
adapter = new SliceAdapter<int>(managedArray); | |
jobHandle = (new ModifySliceJob() { Slice = adapter.NativeSlice }).Schedule(); | |
} | |
void Update() | |
{ | |
if (jobHandle.IsCompleted && !adapter.Disposed) | |
{ | |
adapter.Dispose(); | |
Debug.Log(managedArray[1]); | |
Debug.Log(managedArray[2]); | |
Debug.Log(managedArray[3]); | |
Debug.Log(managedArray[4]); | |
Debug.Log(managedArray[5]); | |
} | |
} | |
} | |
public struct ModifySliceJob : IJob | |
{ | |
public NativeSlice<int> Slice; | |
public void Execute() | |
{ | |
Slice[1] = 1; | |
Thread.Sleep(1000); | |
Slice[2] = 2; | |
Thread.Sleep(1000); | |
Slice[3] = 3; | |
Thread.Sleep(1000); | |
Slice[4] = 4; | |
Thread.Sleep(1000); | |
Slice[5] = 5; | |
} | |
} | |
public unsafe class SliceAdapter<T> : IDisposable | |
where T : struct | |
{ | |
private readonly AtomicSafetyHandle _safetyHandle; | |
private NativeSlice<T> _nativeSlice; | |
public NativeSlice<T> NativeSlice { get { return _nativeSlice; } } | |
public bool Disposed { get; private set; } | |
#if USE_UNITY_PIN_FUNCTION | |
private readonly ulong _pinHandle; | |
#else | |
private readonly GCHandle _gcHandle; | |
#endif | |
public SliceAdapter(T[] managedArray) | |
{ | |
Assert.IsTrue(UnsafeUtility.IsBlittable<T>()); | |
_safetyHandle = AtomicSafetyHandle.Create(); | |
#if USE_UNITY_PIN_FUNCTION | |
NativeSlice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<T>( | |
UnsafeUtility.PinGCObjectAndGetAddress(managedArray, out _pinHandle), | |
UnsafeUtility.SizeOf<T>(), | |
managedArray.Length); | |
#else | |
_gcHandle = GCHandle.Alloc(managedArray, GCHandleType.Pinned); | |
_nativeSlice = NativeSliceUnsafeUtility.ConvertExistingDataToNativeSlice<T>( | |
(void*)_gcHandle.AddrOfPinnedObject(), | |
UnsafeUtility.SizeOf<T>(), | |
managedArray.Length); | |
#endif | |
NativeSliceUnsafeUtility.SetAtomicSafetyHandle(ref _nativeSlice, _safetyHandle); | |
} | |
public void Dispose() | |
{ | |
if (Disposed) return; | |
Disposed = true; | |
// DO NOT Release handle if it is shared | |
AtomicSafetyHandle.Release(_safetyHandle); | |
#if USE_UNITY_PIN_FUNCTION | |
UnsafeUtility.ReleaseGCObject(_pinHandle); | |
#else | |
_gcHandle.Free(); | |
#endif | |
// DO NOT CALL _nativeArray.Dispose(); | |
_nativeSlice = default(NativeSlice<T>); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment