复制 NativeContainer 结构
Copy and reference multiple native containers.
阅读时间6 分钟最后更新于 1 个月前
原生容器是值的类型,这意味着当将原生容器分配给变量时,Unity 会复制 结构,而结构中包含了指向原生容器数据(包括其 )存储位置的指针。这并不会复制 的全部内容。
NativeContainerAtomicSafetyHandleNativeContainer这种场景意味着可能存在多个 结构的副本,且这些副本可能都会引用同一内存区域,且都包含引用同一中央记录的 对象。
NativeContainerAtomicSafetyHandle
NativeContainer 对象副本的工作原理
上图显示了 结构的三个不同副本,它们都表示同一个实际容器。每个副本都指向与原始 相同的存储数据和相同的安全数据。但是,每个 的副本的标志都不同,分别指示了作业可对该副本执行的操作。指向安全数据的指针与标志组合构成了 。
NativeArrayNativeArrayNativeArrayAtomicSafetyHandle版本号
如果 被弃置,则 结构的所有副本都必须将原始 视为无效。弃置原始 意味着用于保存 数据的内存块已被释放。这时,指向存储在各 副本中的数据指针是无效的,强行使用可能导致访问违规。
NativeContainerNativeContainerNativeContainerNativeContainerNativeContainerNativeContainerAtomicSafetyHandleNativeContainer相反,所有记录都包含一个版本号。所有引用该记录的 中都存储了版本号的副本。弃置 NativeContainer 时,Unity 会调用 ,从而让中央记录的版本号递增。此后,记录可被用于其他 实例。
AtomicSafetyHandleRelease()NativeContainer所有剩余的 会将其存储的版本号与中央记录中的版本号进行比较,以测试 是否已弃置。Unity 在调用 和 等方法时会自动执行此测试。
AtomicSafetyHandle NativeContainerCheckReadAndThrowCheckWriteAndThrow动态原生容器的静态视图
动态原生容器的大小可变,允许持续向其中添加元素,例如 (由 Collections 包提供)。这与 等静态原生容器相反,静态原生容器大小固定,无法更改。
NativeList<T>NativeArray<T>使用动态原生容器时,还可以通过另一种接口(即视图)直接访问其数据。视图让您可以对 对象数据设置别名,且无需复制或拥有数据。视图包括枚举器对象(可用于对原生容器元素中的数据进行逐数据访问)以及 等方法(可用于将 视为 进行处理)。
NativeContainerNativeList<T>.AsArrayNativeListNativeArray如果动态原生容器的大小发生变化,则视图通常不具备线程安全性。这是因为,当原生容器的大小发生变化时,Unity 会重新定位数据存储在内存中的位置,从而导致视图所存储的指针无效。
二级版本号
为支持动态原生容器大小发生变化的情况,安全系统会在 中包含二级版本号。此机制与版本控制机制类似,但使用存储在中央记录中的第二个版本号,而该版本号可以独立于第一个版本号进行递增。
AtomicSafetyHandle要使用二级版本号,可以使用 将视图配置为存储在 中的数据。对于更改原生容器大小的操作,或导致现有视图无效的操作,请使用 而非 。还需要为 设置 ,以便在调度写入原生容器的作业时自动使视图无效。
UseSecondaryVersionNativeContainerCheckWriteAndBumpSecondaryVersionCheckWriteAndThrowNativeContainerSetBumpSecondaryVersionOnScheduleWrite当您创建视图并将 复制到视图时,请使用 ,以确保将指向原生容器内存的指针复制到视图中的安全性。
AtomicSafetyHandleCheckGetSecondaryDataPointerAndThrow特殊句柄
使用临时原生容器时,可用的特殊句柄有二:
- :返回可在通过
GetTempMemoryHandle分配的原生容器中使用的Allocator.Temp。当前临时内存范围退出时,Unity 会自动使此句柄无效,因此你无需亲自释放。要测试特定的AtomicSafetyHandle是否为AtomicSafetyHandle返回的句柄,请使用GetTempMemoryHandle。IsTempMemoryHandle - :返回一个全局句柄,可用于由不安全内存支持的临时原生容器。例如,由堆栈内存构造的
GetTempUnsafePtrSliceHandle。无法将使用此句柄的容器传递给作业。NativeSlice