RealityKit发送网格描述符可能导致数据竞争
我有这样一个函数,用于对给定网格进行变换,并返回变换后的网格。
extension MeshResource {
func transformedMesh() async -> MeshResource {
var allDescriptors: [MeshDescriptor] = []
for model in self.contents.models {
for part in model.parts {
var desc = MeshDescriptor(name: part.id)
// build up the desc
// desc.positions = ...
// desc.normals = ...
// desc.textureCoordinates = ...
allDescriptors += [desc]
}
}
let mesh = try! await MeshResource(from: allDescriptors)
return mesh
}
}
这段代码工作得很顺利。
然而,我意识到调用 MeshResource(from: allDescriptors) 可能代价高昂,因此我想事先获取所有描述符,然后在需要时再构造 MeshResource。
于是我把这个函数拆成两个函数。
extension MeshResource {
struct MeshInfo {
let allDescriptors: [MeshDescriptor]
}
func transformedMeshInfo() async -> MeshInfo {
var allDescriptors: [MeshDescriptor] = []
for model in self.contents.models {
for part in model.parts {
var desc = MeshDescriptor(name: part.id)
// build up the desc
// desc.positions = ...
// desc.normals = ...
// desc.textureCoordinates = ...
allDescriptors += [desc]
}
}
return MeshInfo(allDescriptors: allDescriptors)
}
func transformedMesh(info: MeshInfo) async -> MeshResource {
return try! await MeshResource(from: info.allDescriptors)
}
}
这在Swift 6中给我带来编译错误:
将处于主actor隔离的 'info.allDescriptors' 发送给 @concurrent的初始化器 'init(from:)',可能导致 @concurrent与主actor隔离的使用之间的数据竞争
我想知道我的第二段代码里究竟是什么原因导致了这个错误?接下来应该怎么继续?
解决方案
看起来你默认开启了主actor隔离。因此,allDescriptors 和 transformedMesh 都被隔离到主actor。另一方面,MeshResource.init 是一个异步但非隔离的方法。参数 info 和 info.allDescriptors 都处于主actor隔离区域,不能从(也就是不能发送给)一个非隔离的异步方法, according to the rules of RBI。
修复的一种方法是把 transformedMesh 的参数改为 sending 参数。
static func transformedMesh(info: sending MeshInfo) async -> MeshResource
这会将 info 放入一个断开的区域。
这与第一版代码的区别在于,allDescriptors 在第一版代码中被声明为一个局部变量,并初始化为 []。这已经使它处于一个断开的区域,因此可以安全地传递。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。