public static void CheckWriteAndThrow(AtomicSafetyHandle handle) { if (handle.IsAllowedToWrite()) { return; } if (Unity.Jobs.LowLevel.Unsafe.JobsUtility.IsExecutingJob()) { throw new System.InvalidOperationException("You are not allowed to write this native container or resource"); } unsafe { AtomicSafetyNode *node = handle.GetInternalNode(); if (node == null) { throw new System.InvalidOperationException("The safety handle is no longer valid -- a native container or other protected resource has been deallocated"); } // @@TODO Need native support //If !main thread //throw "Native container or resource being used from thread which is not main or belonging to job" // @@TODO Need native support //if (!CheckDidSyncFence(node->writer.fence)) //{ // Assert(!AtomicSafetyHandle::ValidateIsAllowedToWriteEarlyOut(buffer)); // return ReturnErrorMsg(kNativeArrayWriteMainThreadAgainstWriteJob, node->writer, errorMsg); //} // @@TODO Need code IL post processing //for (size_t i = 0; i != node->readers.size(); i++) //{ // // Only allowed to access data if someone called sync fence on the job or on a job that depends on it. // if (!CheckDidSyncFence(node->readers[i].fence)) // { // Assert(!AtomicSafetyHandle::ValidateIsAllowedToWriteEarlyOut(buffer)); // return ReturnErrorMsg(kNativeArrayWriteMainThreadAgainstReadJob, node->readers[i], errorMsg); // } //} if ((node->flags & AtomicSafetyNodeFlags.AllowSecondaryWriting) == 0 && handle.UncheckedIsSecondaryVersion()) { throw new System.InvalidOperationException("Native container has been declared [ReadOnly] but you are attemping to write to it"); } // If we are write protected, but are no longer in a job and no other safety checks failed, we can remove write protection node->version0 &= AtomicSafetyNodeVersionMask.WriteUnprotect; if ((node->flags & AtomicSafetyNodeFlags.AllowSecondaryWriting) == AtomicSafetyNodeFlags.AllowSecondaryWriting) { node->version1 &= AtomicSafetyNodeVersionMask.WriteUnprotect; } } UnityEngine.Assertions.Assert.IsTrue(handle.IsAllowedToWrite()); }
public JobHandle GetWriter() { unsafe { AtomicSafetyNode *node = GetInternalNode(); if (node != null) { return(node->writer.fence); } } return(new JobHandle()); }
public unsafe int GetReaderArray(int maxCount, JobHandle *handles) { AtomicSafetyNode *node = GetInternalNode(); if (node == null) { return(0); } int count = node->readerCount < maxCount ? node->readerCount : maxCount; for (int i = 0; i < count; i++) { handles[i] = node->readers[i].fence; } return(node->readerCount); }
public static void Release(AtomicSafetyHandle handle) { unsafe { // Can throw if corrupted or unallowed job // Otherwise return null if released already (based on version mismatch), where we will throw AtomicSafetyNode *node = handle.GetInternalNode(); if (node == null) { throw new System.InvalidOperationException("The Handle has already been released"); } // Clear all protections and increment version to protect from any other remaining AtomicSafetyHandles node->version0 = (node->version0 & AtomicSafetyNodeVersionMask.ReadWriteDisposeUnprotect) + AtomicSafetyNodeVersionMask.VersionInc; node->version1 = (node->version1 & AtomicSafetyNodeVersionMask.ReadWriteDisposeUnprotect) + AtomicSafetyNodeVersionMask.VersionInc; PushAtomicNode((void *)handle.nodePtrPtr); } }
public static void CheckGetSecondaryDataPointerAndThrow(AtomicSafetyHandle handle) { if (handle.IsAllowedToRead()) { return; } if (Unity.Jobs.LowLevel.Unsafe.JobsUtility.IsExecutingJob()) { throw new System.InvalidOperationException("You are not allowed to read this native container or resource"); } unsafe { AtomicSafetyNode *node = handle.GetInternalNode(); if (node == null) { throw new System.InvalidOperationException("The safety handle is no longer valid -- a native container or other protected resource has been deallocated"); } UnityEngine.Assertions.Assert.IsFalse(handle.UncheckedIsSecondaryVersion()); // @@TODO Need native support //If !main thread //throw "Native container or resource being used from thread which is not main or belonging to job" // @@TODO Need code IL post processing // The primary buffer might (List) might resize // The secondary buffer does not resize (Array) // Thus if it was scheduled as a secondary buffer, we can safely access it //if (node->writer.wasScheduledWithSecondaryBuffer == 1) // return; // @@TODO Need native support //if (!CheckDidSyncFence(node->writer.fence)) //return; } UnityEngine.Assertions.Assert.IsFalse(handle.IsAllowedToRead()); throw new System.InvalidOperationException("The previously scheduled job writes to the NativeList. You must call JobHandle.Complete() on the job before you can cast the NativeList to a NativeArray safely or use NativeList.AsDeferredJobArray() to cast the array when the job executes."); }
public static void CheckReadAndThrow(AtomicSafetyHandle handle) { if (handle.IsAllowedToRead()) { return; } if (Unity.Jobs.LowLevel.Unsafe.JobsUtility.IsExecutingJob()) { throw new System.InvalidOperationException("You are not allowed to read this native container or resource"); } unsafe { AtomicSafetyNode *node = handle.GetInternalNode(); if (node == null) { throw new System.InvalidOperationException("The safety handle is no longer valid -- a native container or other protected resource has been deallocated"); } // @@TODO Need native support //If !main thread //throw "Native container or resource being used from thread which is not main or belonging to job" // @@TODO Need native support //if (!CheckDidSyncFence(node->writer.fence)) //{ // Assert(!AtomicSafetyHandle::ValidateIsAllowedToReadEarlyOut(buffer)); // return ReturnErrorMsg(kNativeArrayReadMainThreadAgainstWriteJob, node->writer, errorMsg); //} // If we are read protected, but are no longer in a job and no other safety checks failed, we can remove read protection node->version0 &= AtomicSafetyNodeVersionMask.ReadUnprotect; node->version1 &= AtomicSafetyNodeVersionMask.ReadUnprotect; } UnityEngine.Assertions.Assert.IsTrue(handle.IsAllowedToRead()); }