[英]Can we use C struct based API directly from Swift?
我离开了 WWDC 2016,了解到我们应该警惕直接从 Swift 使用基于 C 的struct
API。 在Swift 3 中使用 GCD 进行并发编程中,谈到基于 C 的锁,它们非常具体:
...在 Swift 中,由于您拥有整个 Darwin 模块,您实际上会看到基于
struct
的传统 C 锁。 但是,Swift 假设任何struct
都可以移动,并且这不适用于互斥体或锁。 因此,我们真的不鼓励您使用 Swift 中的此类锁。 ...... And if you want something... that looks like the locks that you have in C, then you have to call into Objective-C and introduce a base class in Objective-C that has your lock as an ivar.
然后,您将公开
lock
和unlock
方法,如果您还需要它,还有一个tryLock
,当您将这个 class 子类化时,您将能够从 Swift 调用它。 ...@implementation LockableObject { os_unfair_lock _lock; } - (void)lock { os_unfair_lock_lock(&_lock); } - (void)unlock { os_unfair_lock_unlock(&_lock); } @end
但是,在观看 WWDC 2019Developing a Great Profiling Experience时,我注意到作者是直接从 Swift 使用os_unfair_lock
,没有这个 Objective-C 包装器,有效:
private var workItemsLock = os_unfair_lock()
func subWorkItem(...) {
...
os_unfair_lock_lock(&self.workItemsLock)
...
os_unfair_lock_unlock(&self.workItemsLock)
...
}
根据经验,这种直接使用os_unfair_lock
似乎可行,但这并不意味着什么。 尊重 2016 年 WWDC 视频中的警告,我避免直接从 Swift 使用os_unfair_lock
。
所以,问题是,他们在 2019 年的样本中使用这个 API 是否(稍微)草率? 还是 2016 年的视频在其声明中不正确? 还是自 Swift 3 以来基于 C 的struct
的处理发生了变化,现在使这种模式安全?
使用private var workItemsLock = os_unfair_lock()
的 API 示例在运行时可能会失败。
来自 C 的线程原语需要一个稳定的 memory 位置,因此要使用它们或另一个直接将这些原语之一作为其成员的结构,您必须使用UnsafePointer
。 原因是UnsafePointer
API 在分配了一块 memory 后,memory 是稳定的,不能被编译器移动或轻易复制。
如果您像这样更改示例,它现在是有效的
private var workItemsLock: UnsafeMutablePointer<os_unfair_lock> = {
// Note, somewhere else this will need to be deallocated
var pointer = UnsafeMutablePointer<os_unfair_lock>.allocate(capacity: 1)
pointer.initialize(to: os_unfair_lock())
return pointer
}()
func subWorkItem(...) {
...
os_unfair_lock_lock(self.workItemsLock)
...
os_unfair_lock_unlock(self.workItemsLock)
...
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.