繁体   English   中英

我们可以直接从 Swift 使用基于 API 的 C 结构吗?

[英]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.

然后,您将公开lockunlock方法,如果您还需要它,还有一个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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM